Как связать, упорядочить и отформатировать данные в списке матриц, полученных в результате разделения группы - PullRequest
2 голосов
/ 16 апреля 2020

У меня есть list из matrices, показывающий результаты описательного анализа, полученные в результате предыдущего group_split(), с коэффициентом.

То, что я хотел бы сделать, - это наложение соответствующих matrices с использованием rbind() с помощью функционального решения, которое позволяет итеративно выбирать соответствующие matrices, связывать и форматировать их (т.е. задавать имена строк , имена и индивидуальный порядок строк). Последний шаг - напечатать matrices, содержащий описательные результаты, используя kableExtra.

Моя проблема: Использование rbind() в a для l oop для связывания и итерации по соответствующим триплетам матрицы для rbind их производит только желаемый результат для последнего триплета, но не для всех триплетов. Может быть, кто-то из вас имеет представление о том, где я иду не так. Я рассмотрел подобные вопросы здесь, но не нашел решения моей проблемы.

Вот пример использования tidyverse и kableExtra окружения пакета

# Some random data for an initial df
city <- rep(c(1:3), each = 4) %>% factor () # this is the splitting variable
gender <- rep(c("m", "f", "m", "f", "m", "f", "m", "f", "m", "f", "m", "f")) %>% factor () # this is a factor for a later subgrouping analysis
age <- c(32, 54, 67, 35, 19, 84, 34, 46, 67, 41, 20, 75)
working_yrs <- c(16, 27, 39, 16, 2, 50, 16, 23, 48, 21, 0, 57)
income <- (working_yrs)*50

df <- data.frame(city, gender, age, working_yrs, income)

cities <- city %>% levels () %>% c () # vector needed later for a for loop


# Group splits by city (dfs -> list of lists)
df1 <- select(df, -gender) %>% 
  group_split (city, keep=FALSE)

df2 <- select (df, -income) %>%
  filter(str_detect(gender, "m")) %>% 
  select (city, age, working_yrs) %>%
  group_split (city, keep = FALSE)

df3 <- select (df, -income) %>%
  filter(str_detect(gender, "f")) %>% 
  select (city, age, working_yrs) %>%
  group_split (city, keep = FALSE)

LOL <- c(df1, df2, df3) # list of lists


# Define function for descriptive analysis (list of lists -> list of matrices)
fun_descr <- function(x) {
  c(n=sum(!is.na(x)),
    Percent=((sum(!is.na(x)))/(sum(!is.na(x)) + sum(is.na(x)))*100),
    Mean=mean(x, na.rm = TRUE),
    SD=sd(x, na.rm = TRUE),
    Median=median(x, na.rm = TRUE),
    Quantile=quantile(x, 0.25, na.rm = TRUE),
    Quantile=quantile(x, 0.75, na.rm = TRUE))
}

LOM <- lapply (LOL, function (x) {
  t(apply(x, 2, fun_descr)) %>% round(digits = 1)
})

Пока все хорошо Теперь вот проблема. Мой подход к rbind() соответствующим матричным триплетам, принадлежащим одному и тому же городу, дает правильные результаты только для последнего города.


for (i in 1:length(cities)) {
  bindcity <- rbind(LOM[[i]], LOM[[i+length(cities)]], LOM[[i+(length(cities)*2)]])
}

bindcity 

Если решение for l oop или lapply работает правильно, возвращая список rbound matrices, я ожидал бы отформатировать строки и столбцы результирующего list из matrices следующим образом. К сожалению, поскольку предыдущий шаг не работает должным образом, я пока не смог его протестировать. Я все еще пытаюсь найти первую строку для этой функции, сортирующую строки каждой матрицы в следующем порядке строк 1,4,6,2,5,7,3, чтобы данные соответствовали именам строк, показанным ниже.

nicematrices <- lapply (bindcity, function (x) {
  rownames(x) <- paste(list("Age", "Working years", "Age (male)", "Working years (male)", "Age (female)", "Working years (female)", "Income"))
  colnames(x) <- paste(list("n (valid)", "% (valid)", "Mean", "SD", "Median", "25% Quantile", "75% Quantile"))
  return(x)
})

Последний шаг: печать matrices с использованием kableExtra

for (i in 1:length(nicematrices)) {
print(
  kable(nicematrices[[i]], caption = "Title") %>%
    column_spec(1, bold = T) %>%
    kable_styling("striped", bootstrap_options = "hover", full_width = TRUE)
)}

Ответы [ 2 ]

2 голосов
/ 16 апреля 2020

Следующее использует циклы lapply для получения желаемых связанных матриц и вывода Kable.

bindcity <- lapply(seq_along(cities), function(i){
  rbind(LOM[[i]], LOM[[i+length(cities)]], LOM[[i+(length(cities)*2)]])
})

nicematrices <- lapply(bindcity, function (x) {
  rownames(x) <- c("Age", "Working years", "Income", "Age (male)", "Working years (male)", "Age (female)", "Working years (female)")
  colnames(x) <- c("n (valid)", "% (valid)", "Mean", "SD", "Median", "25% Quantile", "75% Quantile")
  x
})

Два вышеуказанных цикла могут быть упрощены. Однако следующий lapply l oop не создаст список bindcity. Это важно, только если этот список используется после, что не ясно из вопроса. не используется для создания таблиц Kable.

nicematrices <- lapply(seq_along(cities), function (i) {
  x <- rbind(LOM[[i]], LOM[[i+length(cities)]], LOM[[i+(length(cities)*2)]])
  rownames(x) <- c("Age", "Working years", "Income", "Age (male)", "Working years (male)", "Age (female)", "Working years (female)")
  colnames(x) <- c("n (valid)", "% (valid)", "Mean", "SD", "Median", "25% Quantile", "75% Quantile")
  x
})

Теперь для таблиц Kable.

library(kableExtra)

kbl_list <- lapply(nicematrices, function(x){
  kbl <- kable(x, caption = "Title") %>%
    column_spec(1, bold = TRUE) %>%
    kable_styling("striped", 
                  bootstrap_options = "hover",
                  full_width = TRUE)
  print(kbl)
})
2 голосов
/ 16 апреля 2020

Я не знаю, правильно ли я понимаю, но вы пытались добавить свой индекс i в bindcity?

for (i in 1:length(cities)) {
  bindcity[[i]] <- rbind(LOM[[i]], LOM[[i+length(cities)]], LOM[[i+(length(cities)*2)]])
}

В чем может быть ваша проблема здесь в том, что ваш l oop действительно проходит через все итерации, но сохраняет только последнюю, если вы не уверены, что для каждого i сохраняется результат. Вам также нужно будет инициировать привязку до l oop, если вы хотите следовать этим путем. В целом:

bindcity <- c()

for (i in 1:length(cities)) {
  bindcity[[i]] <- rbind(LOM[[i]], LOM[[i+length(cities)]], LOM[[i+(length(cities)*2)]])
}

Вот что возвращает выше:

> bindcity

[[1]]
            n Percent   Mean    SD Median Quantile.25% Quantile.75%
age         4     100   47.0  16.5   44.5         34.2         57.2
working_yrs 4     100   24.5  11.0   21.5         16.0         30.0
income      4     100 1225.0 548.5 1075.0        800.0       1500.0
age         2     100   49.5  24.7   49.5         40.8         58.2
working_yrs 2     100   27.5  16.3   27.5         21.8         33.2
age         2     100   44.5  13.4   44.5         39.8         49.2
working_yrs 2     100   21.5   7.8   21.5         18.8         24.2

[[2]]
            n Percent   Mean     SD Median Quantile.25% Quantile.75%
age         4     100   45.8   27.8   40.0         30.2         55.5
working_yrs 4     100   22.8   20.2   19.5         12.5         29.8
income      4     100 1137.5 1007.8  975.0        625.0       1487.5
age         2     100   26.5   10.6   26.5         22.8         30.2
working_yrs 2     100    9.0    9.9    9.0          5.5         12.5
age         2     100   65.0   26.9   65.0         55.5         74.5
working_yrs 2     100   36.5   19.1   36.5         29.8         43.2

[[3]]
            n Percent   Mean     SD Median Quantile.25% Quantile.75%
age         4     100   50.8   25.1   54.0         35.8         69.0
working_yrs 4     100   31.5   26.0   34.5         15.8         50.2
income      4     100 1575.0 1299.0 1725.0        787.5       2512.5
age         2     100   43.5   33.2   43.5         31.8         55.2
working_yrs 2     100   24.0   33.9   24.0         12.0         36.0
age         2     100   58.0   24.0   58.0         49.5         66.5
working_yrs 2     100   39.0   25.5   39.0         30.0         48.0
...