如果运行两次,apply函数将返回列表列表

时间:2018-10-12 17:17:59

标签: r

我有这样的df

a1 <- c(1,2,NA)
a2 <- c(3,4,NA)
a3 <- c(4,5,6)
a1_fill <- c(1,2,3)
a2_fill <- c(3,4,5)
a3_fill <- c(4,5,6)
b1 <- c(4,3,1)
b2 <- c(2,NA,9)
b3 <- c(NA,3,5)
b1_fill <- c(4,3,1)
b2_fill <- c(2,1,9)
b3_fill <- c(8,3,5)
df <- data.frame(a1,a2,a3,b1,b2,b3,a1_fill,a2_fill,a3_fill,b1_fill,b2_fill,b3_fill)

我想用fill列中的值创建两个新列,这些列不会出现在相应的ab列中。我是这样的

df$missingA <- apply(df,1,function(x) setdiff(x[which(grepl("a",names(x),fixed = TRUE) & grepl("fill",names(x),fixed = TRUE))],x[which(grepl("a",names(x),fixed = TRUE) & !grepl("fill",names(x),fixed = TRUE))]))
df$missingB <- apply(df,1,function(x) setdiff(x[which(grepl("b",names(x),fixed = TRUE) & grepl("fill",names(x),fixed = TRUE))],x[which(grepl("b",names(x),fixed = TRUE) & !grepl("fill",names(x),fixed = TRUE))]))

由于某种原因,当我运行上面的代码时,第二行运行返回一行列表,而第一行返回数字列表。为什么会这样?

1 个答案:

答案 0 :(得分:0)

这取决于行的运行顺序。我们可以使用下面的代码来确定列中元素的类

class(df$missingA[[1]]) # Class of first element is numeric
class(df$missingB[[1]]) # Class of first element is list

从干净的数据集开始,如果首先创建missingB,然后创建missingA,则会看到missingA将是列表列表,而missingB将是数字列表(类型相反)。

df$missingB <- apply(df,1,function(x) 
  setdiff(
    x[which(
      grepl("b",names(x),fixed = TRUE) & 
      grepl("fill",names(x),fixed = TRUE))
    ],
    x[which(
      grepl("b",names(x),fixed = TRUE) & 
      !grepl("fill",names(x),fixed = TRUE))
    ]
  )
)


df$missingA <- apply(df,1,function(x) 
  setdiff(
    x[which(
      grepl("a",names(x),fixed = TRUE) & 
      grepl("fill",names(x),fixed = TRUE))
    ],
    x[which(
      grepl("a",names(x),fixed = TRUE) & 
      !grepl("fill",names(x),fixed = TRUE))
    ]
  )
)

class(df$missingA[[1]]) # Class of first element is list
class(df$missingB[[1]]) # Class of first element is numeric

我的猜测是正在发生以下情况。您将从一个仅包含数字列的数据框开始。 R尝试通过将列表的类型与数字匹配来提供帮助。当添加第二列时,数据框不再 纯粹由数字列组成,现在列出了其中一种类型,因此R不会尝试更新类型。

要对此进行测试,您可以在添加missingA和missingB之前添加一个无数字列,例如:

df$text <- list("a","b","C")

现在missingA和missingB都将创建为列表列表

保留类型的另一种方法是通过apply语句生成类型,方法是将输出分配给中间变量

missingA <- apply(df,1,function(x) 
setdiff(
  x[which(
    grepl("a",names(x),fixed = TRUE) & 
    grepl("fill",names(x),fixed = TRUE))
  ],
  x[which(
    grepl("a",names(x),fixed = TRUE) & 
    !grepl("fill",names(x),fixed = TRUE))
  ]
 )
)

df$missingA <- missingA

总而言之,您看到的差异不是由apply语句或它们产生的输出引起的,而是由将数据添加到数据帧的方式引起的。希望这会有所帮助!