Создайте data.frame, где столбец - это список

80

Я знаю, как добавить столбец списка:

> df <- data.frame(a=1:3)
> df$b <- list(1:1, 1:2, 1:3)
> df
  a       b
1 1       1
2 2    1, 2
3 3 1, 2, 3

Это работает, но нет:

> df <- data.frame(a=1:3, b=list(1:1, 1:2, 1:3))
Error in data.frame(1L, 1:2, 1:3, check.names = FALSE, stringsAsFactors = TRUE) : 
  arguments imply differing number of rows: 1, 2, 3

Почему?

Кроме того, есть ли способ создать df(см. Выше) за один вызов data.frame?

Flodel
источник

Ответы:

103

Слегка неясно, от ?data.frame:

Если список, фрейм данных или матрица передаются в 'data.frame', это как если бы каждый компонент или столбец был передан как отдельный аргумент (за исключением матриц класса '' model.matrix '' и матриц, защищенных 'I ' ).

(курсив мой).

Так

data.frame(a=1:3,b=I(list(1,1:2,1:3)))

вроде работает.

Бен Болкер
источник
17
Для интересующихся «Я» означает «Запретить интерпретацию / преобразование объектов». Он создает идентичный объект, но с добавлением «AsIs» к набору классов. Класс «AsIs» существует только для того, чтобы его могли прочитать функции data.frame () и formula (). Узнайте больше здесь .
pwilcox 01
2
потрясающе, спасибо за решение. хотя просто Iдля
запрета интерпретации
@pwilcox очень интересно. Есть ли способ вызвать объект, чтобы понять, защищен ли он мной? Я так думаю class()? например I(iris) -> i; i %>% class() 3 [1] "AsIs" "data.frame"(возвращает класс AsIs)
stevec
33

Если вы работаете с data.tables, то можете избежать звонкаI()

library(data.table)
# the following works as intended
data.table(a=1:3,b=list(1,1:2,1:3))

   a     b
1: 1     1
2: 2   1,2
3: 3 1,2,3
Mnel
источник
Это недооцененная особенность data.tableс большим отрывом
data princess
22

data_frames ( по- разному называют tibbles, tbl_df, tbl) изначально поддерживает создание столбцов списка с помощью data_frameконструктора. Чтобы использовать их, загрузите с ними одну из многих библиотек, например tibble, dplyrили tidyverse.

> data_frame(abc = letters[1:3], lst = list(1:3, 1:3, 1:3))
# A tibble: 3 × 2
    abc       lst
  <chr>    <list>
1     a <int [3]>
2     b <int [3]>
3     c <int [3]>

Они действительно находятся data.framesпод капотом, но несколько видоизменены. Их почти всегда можно использовать как обычно data.frames. Единственное исключение, которое я обнаружил, - это то, что когда люди выполняют несоответствующие проверки классов, они вызывают проблемы:

> #no problem
> data.frame(x = 1:3, y = 1:3) %>% class
[1] "data.frame"
> data.frame(x = 1:3, y = 1:3) %>% class == "data.frame"
[1] TRUE
> #uh oh
> data_frame(x = 1:3, y = 1:3) %>% class
[1] "tbl_df"     "tbl"        "data.frame"
> data_frame(x = 1:3, y = 1:3) %>% class == "data.frame"
[1] FALSE FALSE  TRUE
> #dont use if with improper testing!
> if(data_frame(x = 1:3, y = 1:3) %>% class == "data.frame") "something"
Warning message:
In if (data_frame(x = 1:3, y = 1:3) %>% class == "data.frame") "something" :
  the condition has length > 1 and only the first element will be used
> #proper
> data_frame(x = 1:3, y = 1:3) %>% inherits("data.frame")
[1] TRUE

Я рекомендую прочитать о них в R 4 Data Science (бесплатно).

CoderGuy123
источник
1
R движется и растет, и я думаю, что это ответ на вопрос 2018 года, и его следует как-то обозначить как таковой.
Fitzroy Hogsflesh
Если он достаточно популярен, он поднимется на вершину. Многие из нас до сих пор используют базовый R ...
Бен Болкер