过滤掉数据框列表中没有 Z 列的所有数据框?
Filter out all data frames which don't have the column Z in a list of data frames?
我有一个包含六个数据框的列表,其中 5/6 个数据框有一列“Z”。要继续我的脚本,我需要删除没有 Z 列的数据框,所以我尝试了以下代码:
for(i in 1:length(df)){
if(!("Z" %in% colnames(df[[i]])))
{
df[[i]] = NULL
}
}
这似乎真的可以完成这项工作(它从列表中删除了一个数据框,它没有列 Z),但是我仍然收到一条消息“df [[i] 中的错误] :下标越界”。为什么会这样,我该如何解决这个错误?
如果 df
是您的 6 个数据帧列表,您可以这样做:
df <- df[sapply(df, \(i) "Z" %in% colnames(i))]
你得到错误的原因是你的循环将减少 df
的长度,这样 i
最终将超过 df 的(新)长度。如果 df
中唯一没有列 Z
的帧是最后一帧,则不会出现错误。
基本 Filter
函数在这里运行良好:
df <- Filter(\(x) "Z" %in% names(x), df)
至于为什么您的方法不起作用,for(i in 1:length(df))
遍历了原始 length(df)
中的每个项目。一旦 df[[i]] = NULL
发生一次,那么 df
就会比循环开始时短,因此最后一次迭代将越界。而且你还会跳过一些项目:如果 df[[2]]
被删除,那么原来的 df[[3]]
现在是 df[[2]]
,而当前的 df[[3]]
原来是 df[[4]]
,所以你跳过原来的 df[[3]]
而没有检查它。经验教训:不要在遍历对象的过程中更改对象的长度。
使用discard
:
list_df <- list(df1, df2)
purrr::discard(list_df, ~any(colnames(.x) == "Z"))
输出:
[[1]]
A B
1 1 3
2 3 4
如您所见,它删除了第一个包含 Z 列的数据框。
数据
df1 <- data.frame(A = c(1,2),
Z = c(1,4))
df2 <- data.frame(A = c(1,3),
B = c(3,4))
我有一个包含六个数据框的列表,其中 5/6 个数据框有一列“Z”。要继续我的脚本,我需要删除没有 Z 列的数据框,所以我尝试了以下代码:
for(i in 1:length(df)){
if(!("Z" %in% colnames(df[[i]])))
{
df[[i]] = NULL
}
}
这似乎真的可以完成这项工作(它从列表中删除了一个数据框,它没有列 Z),但是我仍然收到一条消息“df [[i] 中的错误] :下标越界”。为什么会这样,我该如何解决这个错误?
如果 df
是您的 6 个数据帧列表,您可以这样做:
df <- df[sapply(df, \(i) "Z" %in% colnames(i))]
你得到错误的原因是你的循环将减少 df
的长度,这样 i
最终将超过 df 的(新)长度。如果 df
中唯一没有列 Z
的帧是最后一帧,则不会出现错误。
基本 Filter
函数在这里运行良好:
df <- Filter(\(x) "Z" %in% names(x), df)
至于为什么您的方法不起作用,for(i in 1:length(df))
遍历了原始 length(df)
中的每个项目。一旦 df[[i]] = NULL
发生一次,那么 df
就会比循环开始时短,因此最后一次迭代将越界。而且你还会跳过一些项目:如果 df[[2]]
被删除,那么原来的 df[[3]]
现在是 df[[2]]
,而当前的 df[[3]]
原来是 df[[4]]
,所以你跳过原来的 df[[3]]
而没有检查它。经验教训:不要在遍历对象的过程中更改对象的长度。
使用discard
:
list_df <- list(df1, df2)
purrr::discard(list_df, ~any(colnames(.x) == "Z"))
输出:
[[1]]
A B
1 1 3
2 3 4
如您所见,它删除了第一个包含 Z 列的数据框。
数据
df1 <- data.frame(A = c(1,2),
Z = c(1,4))
df2 <- data.frame(A = c(1,3),
B = c(3,4))