为什么foreach会返回列表列表

时间:2016-01-19 03:53:21

标签: r dataframe

我让自己陷入困境,试图了解下面的代码是怎么回事。我正在尝试为data.frame中的每一行创建一个向量,然后附加到原始行。我希望下面的代码返回一个数组列表。它似乎返回一个列表列表,内部列表包含数组?我怎么能得到我想要的东西 - 一个新的列附加每个元素是一个数组?

df <- mtcars 

library(foreach)
library(iterators)

df$x = foreach (row = iter(df, by='row'))  %do%  {
  profile <- as.numeric(row[,c('mpg', 'cyl', 'disp')])
  return(profile)
}

我期待结果:

df[1,]$x == as.numeric(df[1,c('mpg', 'cyl', 'disp')])

而不是

df[1,]$x[1] == as.numeric(df[1,c('mpg', 'cyl', 'disp')])

(我在使用==来表示两个集合是一样的,我意识到R可能没有以这种方式实现列表相等运算符)

2 个答案:

答案 0 :(得分:1)

此问题不是由foreach引起的。您希望将向量分配给数据框的单元(或元素)而不是数据框的列。 foreach函数必须将此向量强制转换为list

例如。

df1 <- data.frame(x1=1:4, x2=letters[1:4], stringsAsFactors = FALSE)
df1$x1[1] <- 5:8
# Warning message:
# In df1$x1[1] <- 5:8 :
#   number of items to replace is not a multiple of replacement length
df1
#   x1 x2
# 1  5  a
# 2  2  b
# 3  3  c
# 4  4  d
df1$x1[1] <- list(5:8)
df1
#           x1 x2
# 1 5, 6, 7, 8  a
# 2          2  b
# 3          3  c
# 4          4  d
df1$x1[1]
# [[1]]
# [1] 5 6 7 8
df1$x1[[1]]
# [1] 5 6 7 8

实际上,您应该使用[[代替[

df[1, ]$x[[1]] == as.numeric(df[1,c('mpg', 'cyl', 'disp')])
# [1] TRUE TRUE TRUE

由于list[1]仍然是一个列表,而list[[1]]提取list的第一个元素。请参阅下面的示例。

lst1 <- list(x1=1:4, x2=letters[1:5])
lst1[1]
# $x1
# [1] 1 2 3 4
lst1[[1]]
# [1] 1 2 3 4

此外,您可以使用:

df$x[[1]]
[1]  21   6 160

而不是:

df[1, ]$x[[1]]
# [1]  21   6 160

答案 1 :(得分:1)

默认情况下,foreach包会返回输入列表的列表(每次迭代一个列表)。这就是为什么你最终输出“错误”的原因。您可以使用foreach循环中的.combine选项更改此设置。如果我理解正确,你希望逐行追加。这可以通过指定.combine = 'rbind'来实现,rbind使用熟悉的.inorder = FALSE函数来组合每个循环迭代的输出。如果订单无关紧要,您还应指定TRUE以加快代码速度。 (foreach (row = iter(df, by='row'), .combine='rbind') %do% ...是默认值,因此如果订单相关,您无需费心。) 因此,请尝试使用Line-height,看看它是否能胜任。