Попытка сохранить имена матриц и строк при объединении в один фрейм данных - PullRequest
0 голосов
/ 30 октября 2018

У меня есть список матриц, которые имеют одинаковое количество столбцов, но имеют различное количество и наименование строк. Они выглядят примерно так:

$Name1
                  c1 c2 c3 c4 c5 c6
Spec1              0  2  0  1  0  0   
Spec2              1  0  1  0  0  0
Spec3              1  0  1  0  0  0

$Name2
                  c1 c2 c3 c4 c5 c6
Spec1              0  0  0  0  1  0   
Spec4              0  0  0  1  0  0
Spec5              0  0  0  0  0  1

Я пытаюсь объединить их все в один кадр данных, сохраняя при этом как имена строк, так и имена матриц. Примерно так я и пытаюсь получить:

                        c1 c2 c3 c4 c5 c6
Name1Spec1              0  2  0  1  0  0   
Name1Spec2              1  0  1  0  0  0
Name1Spec3              1  0  1  0  0  0
Name2Spec1              0  0  0  0  1  0   
Name2Spec4              0  0  0  1  0  0
Name2Spec5              0  0  0  0  0  1

do.call (rbind, ...) получает данные так, как я хочу, но я не смог понять, как получить имена, которые будут сохранены или объединены таким образом. Я также попробовал несколько способов составить список имен отдельно и потерпел неудачу на этих фронтах. Конечный фрейм данных должен быть 1113 строк, но в списке 358 матриц. Я пробовал много неумелых вещей, но я думаю, что-то вроде этого должно быть близко?

list.names<-list()
for(i in 1:length(ListofMatrices)){
  list.names[i]<-rownames(ListofMatrices[[i]])
}

Я чувствую, что упускаю что-то явно очевидное с lapply или настройкой цикла.

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Альтернативное решение с использованием purrr :: map и dplyr (что может быть, а может и не быть проще / более интуитивным, чем решение r2evans):

# Recreate your data:
test <- list(Name1 = matrix(data = c(0,2,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0), 
                        row = 3, ncol = 6,
                        dimnames = list(c("Spec1", "Spec2", "Spec3"), 
                                        c("c1", "c2", "c3", "c4", "c5", "c6"))),
         Name2 = matrix(data = c(0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1), 
                        nrow = 3, ncol = 6,
                        dimnames = list(c("Spec1", "Spec4", "Spec5"), 
                                        c("c1", "c2", "c3", "c4", "c5", "c6"))))

df <- map_dfr(1:length(test), ~test[[.x]] %>% 
      as.data.frame() %>% 
      mutate(items = names(test[.x]),
             specs = row.names(test[[.x]]),
             combined_names = paste0(items, specs)) %>% 
      select(9, 1:6))

df
  combined_names c1 c2 c3 c4 c5 c6
1     Name1Spec1  0  1  1  0  1  0
2     Name1Spec2  2  0  0  0  0  0
3     Name1Spec3  0  0  1  0  1  0
4     Name2Spec1  0  0  0  1  0  0
5     Name2Spec4  0  1  0  0  0  0
6     Name2Spec5  0  0  0  0  0  1

Это может быть немного проще для анализа, если мы вытащим преобразование как его собственную функцию:

df_extractor <- function(x) {
  test[[x]] %>% as.data.frame() %>% # Take the data from each matrix and convert it into a data frame
    mutate(items = names(test[x]), # This extracts the name of each list
           specs = row.names(test[[x]]), # This extracts the original row names
           combined_names = paste0(items, specs)) %>% # Concatenate them together in your style above
    select(9, 1:6) # Select and reorder columns.
}

df <- map_dfr(1:length(test), ~df_extractor(.x)) # use map_dfr to bind the resulting data frames together.
0 голосов
/ 30 октября 2018

Не должно быть необходимости использовать цикл for. Если l ваш список кадров ...

do.call(rbind, l)
#             c1 c2 c3 c4 c5 c6
# Name1.Spec1  0  2  0  1  0  0
# Name1.Spec2  1  0  1  0  0  0
# Name1.Spec3  1  0  1  0  0  0
# Name2.Spec1  0  2  0  1  0  0
# Name2.Spec4  1  0  1  0  0  0
# Name2.Spec5  1  0  1  0  0  0
# Name2.Spec6  1  0  1  0  0  0

Точное совпадение с тем, что вы просили: просто дополнительная точка в названии строки. Если вы действительно хотите, чтобы это удалили, два варианта:

rn <- mapply(paste0, rep(names(l), sapply(l, nrow)), unlist(sapply(l, rownames)))
rn
#        Name1        Name1        Name1        Name2        Name2        Name2        Name2 
# "Name1Spec1" "Name1Spec2" "Name1Spec3" "Name2Spec1" "Name2Spec4" "Name2Spec5" "Name2Spec6" 
out <- do.call(rbind, l)
rownames(out) <- rn
out
#            c1 c2 c3 c4 c5 c6
# Name1Spec1  0  2  0  1  0  0
# Name1Spec2  1  0  1  0  0  0
# Name1Spec3  1  0  1  0  0  0
# Name2Spec1  0  2  0  1  0  0
# Name2Spec4  1  0  1  0  0  0
# Name2Spec5  1  0  1  0  0  0
# Name2Spec6  1  0  1  0  0  0

или

out <- do.call(rbind, l)
rownames(out) <- gsub("\\.", "", rownames(out))

(хотя последнее будет неправильным, если у вас, естественно, есть точки в любом из имен).


Данные. (Я добавил одну строку во второй кадр, чтобы убедиться в правильности именования новой строки.)

l <- setNames(list(
  read.table(header=TRUE, text='
                  c1 c2 c3 c4 c5 c6
Spec1              0  2  0  1  0  0   
Spec2              1  0  1  0  0  0
Spec3              1  0  1  0  0  0'),
  read.table(header=TRUE, text='
                  c1 c2 c3 c4 c5 c6
Spec1              0  2  0  1  0  0   
Spec4              1  0  1  0  0  0
Spec5              1  0  1  0  0  0
Spec6              1  0  1  0  0  0')
), c("Name1", "Name2"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...