Заполнение фрейма данных списками в R - PullRequest
2 голосов
/ 08 июня 2019

Я хочу заполнить столбец фрейма данных списками.На основании примера кода, который я нашел здесь :

d <- data.frame(id=1:2, name=c("Jon", "Mark"))
d
d$children <-  list(list("Mary", "James"), list("Greta", "Sally"))
d

Я ожидал, что следующий код будет работать:

d <- data.frame(id=1:2, name=c("Jon", "Mark"))
d
d["children"] <-  list(list("Mary", "James"), list("Greta", "Sally"))
d

, но он выдал ошибку:

Warning message:
In `[<-.data.frame`(`*tmp*`, "children", value = list(list("Mary",  :
  provided 2 variables to replace 1 variables

Основываясь на прочтении этого поста и этого ответа Я изменил код так:

d <- data.frame(id=1:2, name=c("Jon", "Mark"))
d
d["children"] <-  list(list(list("Mary", "James"), list("Greta", "Sally")))
d

, который работал отлично.Вопрос в том, что здесь происходит?Что делает дополнительный вызов list?Спасибо

Ответы [ 2 ]

1 голос
/ 08 июня 2019

Здесь происходит пара вещей.R производит различное поведение при индексации с одиночными скобками [ ] или с двойными скобками [[ ]].Короче говоря, при использовании одинарных скобок для индексации во фрейме данных R ожидает (или возвращает) список объектов .При использовании двойных скобок возвращается базовый вектор .

Обратите внимание, что первый приведенный ниже пример с одиночными скобками сохраняет структуру и наименование столбца фрейма данных, а двойные скобкиПример возвращает примитивное содержимое столбца как вектор.

> str(mtcars['mpg'])
'data.frame':   32 obs. of  1 variable:
 $ mpg: num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...

> str(mtcars[['mpg']])
 num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...

Чтобы ответить на ваш вопрос о том, почему лишний вызов list() вообще помогает, str может пролить свет на этот вопрос:

Ваш исходный код, без дополнительного list(), представляет собой список длиной 2:

> str(list(list("Mary", "James"), list("Greta", "Sally")))

List of 2
 $ :List of 2
  ..$ : chr "Mary"
  ..$ : chr "James"
 $ :List of 2
  ..$ : chr "Greta"
  ..$ : chr "Sally"

Это не удается, поскольку d['children'] ожидает сопоставления с объектом длиной 1. Однако,добавление дополнительного list() создает «внешний» список длины 1, поэтому назначение выполняется успешно.

str(list(list(list("Mary", "James"), list("Greta", "Sally"))))

List of 1
 $ :List of 2
  ..$ :List of 2
  .. ..$ : chr "Mary"
  .. ..$ : chr "James"
  ..$ :List of 2
  .. ..$ : chr "Greta"
  .. ..$ : chr "Sally"

Наконец, ваш исходный код (без дополнительного list()) сработал бы, если бы вы использовали doubleиндексирование скобок:

d[["children"]] <-  list(list("Mary", "James"), list("Greta", "Sally"))
0 голосов
/ 08 июня 2019

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

> d <- data.frame(id=1:2, name=c("Jon", "Mark"))
> d
  id name
1  1  Jon
2  2 Mark
> add <- list(list("Mary", "James"), list("Greta", "Sally"))
> d$children <- add
> d
  id name     children
1  1  Jon  Mary, James
2  2 Mark Greta, Sally
> str(d$children)
List of 2                                  # d$children is a list of 2
 $ :List of 2
  ..$ : chr "Mary"
  ..$ : chr "James"
 $ :List of 2
  ..$ : chr "Greta"
  ..$ : chr "Sally"
> str(add)
List of 2                                  # add is a list of 2
 $ :List of 2
  ..$ : chr "Mary"
  ..$ : chr "James"
 $ :List of 2
  ..$ : chr "Greta"
  ..$ : chr "Sally"

Это работает, потому что lhs и rhs d$children <- add являются списками с 2 элементами.

> d <- data.frame(id=1:2, name=c("Jon", "Mark"))
> d
  id name
1  1  Jon
2  2 Mark
> add <- list(list("Mary", "James"), list("Greta", "Sally"))
> d["children"] <- add
Warning message:
In `[<-.data.frame`(`*tmp*`, "children", value = list(list("Mary",  :
  provided 2 variables to replace 1 variables
> d
  id name children
1  1  Jon     Mary
2  2 Mark    James
> str(d["children"])
'data.frame':   2 obs. of  1 variable:     # d["children"] is 1 var. with 2 obs.
 $ children:List of 2
  ..$ : chr "Mary"
  ..$ : chr "James"
> str(add)
List of 2                                  # add is a list of 2
 $ :List of 2
  ..$ : chr "Mary"
  ..$ : chr "James"
 $ :List of 2
  ..$ : chr "Greta"
  ..$ : chr "Sally"

Это не работает, потому что lhs из d$children <- add is "1 вар. С 2 об. "но rhs - это «список из 2».

> d <- data.frame(id=1:2, name=c("Jon", "Mark"))
> add <- list(list(list("Mary", "James"), list("Greta", "Sally")))
> d["children"] <- add
> d
  id name     children
1  1  Jon  Mary, James
2  2 Mark Greta, Sally
> str(d["children"])
'data.frame':   2 obs. of  1 variable:     # d["children"] is 1 var. with 2 obs.
 $ children:List of 2
  ..$ :List of 2
  .. ..$ : chr "Mary"
  .. ..$ : chr "James"
  ..$ :List of 2
  .. ..$ : chr "Greta"
  .. ..$ : chr "Sally"
> str(add)
List of 1                                  # add is 1 list with 2 lists
 $ :List of 2
  ..$ :List of 2
  .. ..$ : chr "Mary"
  .. ..$ : chr "James"
  ..$ :List of 2
  .. ..$ : chr "Greta"
  .. ..$ : chr "Sally"

Здесь номенклатура немного нелогична, но если вы согласитесь, что список должен быть внутри списка, чтобы считаться списком, то приведенный вышеработает, потому что lhs d$children <- add это «1 вар. с 2 акциями».и rhs - это "1 список с 2 списками".Обратите внимание на симметрию 1var: 2lists :: 1list: 2lists.

> d <- data.frame(id=1:2, name=c("Jon", "Mark"))
> d
  id name
1  1  Jon
2  2 Mark
> add <- list(list("Mary", "James"), list("Greta", "Sally"))
> d[["children"]] <- add
> d
  id name     children
1  1  Jon  Mary, James
2  2 Mark Greta, Sally
> str(d[["children"]])
List of 2                                  # d[["children"]] is a list of 2
 $ :List of 2
  ..$ : chr "Mary"
  ..$ : chr "James"
 $ :List of 2
  ..$ : chr "Greta"
  ..$ : chr "Sally"
> str(add)
List of 2                                  # add is a list of 2
 $ :List of 2
  ..$ : chr "Mary"
  ..$ : chr "James"
 $ :List of 2
  ..$ : chr "Greta"
  ..$ : chr "Sally"

Как и в первом примере, это работает, потому что lhs и rhs d$children <- add являются списками с 2 элементами.

Я до сих пор не уверен, как должна вызываться структура add в случаях, когда str(add) оценивается как List of 2..., но это может быть не важно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...