Создать фрейм данных, сопоставляя его по первым элементам списка - PullRequest
0 голосов
/ 02 февраля 2019

Я хочу создать фрейм данных на основе первого элемента списка.В частности, у меня есть

Один вектор, содержащий переменные (names1); Один список, который содержит две переменные (некоторые vars1 и значения); И конечный продукт должен представлять собой data.frame с "names1", который содержит столько строк, сколько совпадает регистр. Если нет совпадения между конкретным списком и вектором, это должно быть NA. Значения также могут быть факторами или строками.
names1 <- c("a", "b", "c")
dat1 <- data.frame(names1 =c("a", "b", "c", "f"),values= c("val1", 13, 11, 0))
   dat1$values <- as.factor(dat1$values)
dat2 <- data.frame(names1 =c("a", "b", "x"),values= c(12, 10, 2))
   dat2$values <- as.factor(dat2$values)
list1 <- list(dat1, dat2)

Результатом должен быть новый фрейм данных с переменными «имена» и всеми значениями, которые соответствуют каждой из частей списка:

 a      b    c
 val1   13   11
 12     10   NA

Ответы [ 5 ]

0 голосов
/ 03 февраля 2019

Для полноты, вот подход с использованием dcast() и rowid():

library(data.table)
nam <- names1   # avoid name conflict with column name
rbindlist(list1)[names1 %in% nam, dcast(.SD, rowid(names1) ~ names1)][, names1 := NULL][]
      a  b    c
1: val1 13   11
2:   12 10 <NA>

Илиболее кратко выберите столбцы после изменения формы:

library(data.table)
rbindlist(list1)[, dcast(.SD, rowid(names1) ~ names1)][, .SD, .SDcols = names1]
0 голосов
/ 02 февраля 2019

В базе R

t(sapply(list1, function(x) setNames(x$values, names)[match(names, x$names)]))
#       a  b  c
# [1,] 25 13 11
# [2,] 12 10 NA
0 голосов
/ 02 февраля 2019

Смесь базы R и dplyr.Для каждого элемента списка мы создаем фрейм данных с 1 строкой.Используя строку dplyr rbind_list, свяжите их вместе, а затем установите подмножество только тех столбцов, которые нам нужны, используя names.

library(dplyr)

rbind_list(lapply(list1, function(x) 
        setNames(data.frame(t(x$values)), x$names)))[names]

#     a     b     c
#   <dbl> <dbl> <dbl>
#1    25    13    11
#2    12    10    NA

Вывод без подмножества выглядит следующим образом

rbind_list(lapply(list1, function(x) setNames(data.frame(t(x$values)), x$names)))

#     a     b     c     x
#   <dbl> <dbl> <dbl> <dbl>
#1    25    13    11    NA
#2    12    10    NA     2
0 голосов
/ 02 февраля 2019

Использование только базы R

body <- do.call('rbind', lapply(list1, function(list.element){
  element.vals <- list.element[['values']]
  element.names <- list.element[['names']]
  names(element.vals) <- element.names
  return.vals <- element.vals[names]
  if(all(is.na(return.vals))) NULL else return.vals
}))

df <- as.data.frame(body)
names(df) <- names
df
0 голосов
/ 02 февраля 2019

Одним из вариантов будет цикл по list ('list1'), filter столбцу 'names' на основе вектора 'names', преобразование его в один набор данных при создании столбца идентификации с .id, spread от 'long' до 'wide' и удалите столбец 'grp'

library(tidyverse)
map_df(list1, ~   .x %>% 
                     filter(names %in% !! names), .id = 'grp') %>%           
      spread(names, values) %>% 
      select(-grp)   
#      a     b     c    
#1    25    13    11
#2    12    10    NA

Или другой вариант - связать наборы данных вместе с bind_rows, создал идентификатор группы«grp» для указания элемента list, filter строк путем выбора только столбца «names», который соответствует «names» vector и spread от «long» до «wide»

bind_rows(list1, .id = 'grp') %>%
   filter(names %in% !! names) %>% 
   spread(names, values)

ПРИМЕЧАНИЕ. Лучше не использовать зарезервированные ключевые слова для указания имен объектов (names).Кроме того, чтобы избежать путаницы, объект должен отличаться от имен столбцов объекта dataframe.


Это также может быть сделано только с base R.Создайте идентификатор группы с Map, rbind элементами list в одном наборе данных, subset строками, сохраняя только значения из 'names' vector и reshape от 'long' до 'широкий '

df1 <- subset(do.call(rbind, Map(cbind, list1, 
          ind = seq_along(list1))), names %in% .GlobalEnv$names)   
reshape(df1, idvar = 'ind', direction = 'wide', timevar = 'names')[-1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...