用R中的列表填充数据框

时间:2019-06-07 22:50:22

标签: r list

我想用列表填充数据框的一列。根据示例代码,我发现了here

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

基于阅读this postthis answer的代码,我将其更改为:

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

效果很好。问题是,这是怎么回事?对list的额外调用完成了什么?谢谢

2 个答案:

答案 0 :(得分:1)

这里发生了几件事。当使用单括号[ ]或双括号[[ ]]进行索引时,R会产生不同的行为。简而言之,当使用单括号将数据帧索引时,R期望(或返回)列表对象。使用双括号时,将返回基础的 vector

请注意,下面的第一个示例带有单括号,保留了数据框列的结构和命名,而双括号示例则将列的原始内容作为矢量返回。

> 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())就可以使用:

d[["children"]] <-  list(list("Mary", "James"), list("Greta", "Sally"))

答案 1 :(得分:0)

@jdobres的答案使我开始研究以下示例,这有助于我理解(有点)发生了什么。

> 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"

之所以可行,是因为d$children <- add的lhs和rhs都是具有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"

这不起作用,因为d$children <- add的lhs是“ 1 var。with 2 obs”。但是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"

这里的命名有点不合逻辑,但是如果您接受一个列表必须在列表中才能计为列表,则上述方法有效,因为d$children <- add的lhs是“ 1 var。with 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"

像第一个示例一样,之所以有用,是因为d$children <- add的lhs和rhs都是具有2个项目的列表。

我仍然不确定在add评估为str(add)的情况下应该调用List of 2...的封闭结构,但这可能并不重要。