首页 > 解决方案 > 如果运行两次,应用函数返回列表列表

问题描述

我有一个这样的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未出现在相应列a或列中的列b。我这样做

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))]))

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

标签: r

解决方案


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

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都将被创建为列表列表

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

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

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


推荐阅读