【问题标题】:filtering a data frame by a varying number of logical columns通过不同数量的逻辑列过滤数据框
【发布时间】:2014-03-25 20:23:53
【问题描述】:

我有一个问题,我确定有一个我找不到的优雅解决方案。

我有一个函数可以创建具有一组不同逻辑向量的数据框。在函数结束时,我想组合所有现有的逻辑向量。潜在的名称是已知的,但足以使 if 语句的各种排列不可行。

例如下面的两个数据表。潜在的逻辑向量是“night”、“pet”、“rising”,其中会存在 1 到 3 个。我想要能够可靠地组合任何存在的逻辑向量的代码。

我想出了与潜在列的名称相匹配的列号列表,但无法将其带回家

希望这很清楚,感谢您的帮助

df1 <- structure(list(hour = structure(c(1123624800, 1123628400, 1123632000, 
1123635600, 1123639200), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    night = c(FALSE, FALSE, TRUE, TRUE, TRUE), pet = c(TRUE, 
    TRUE, TRUE, TRUE, TRUE)), .Names = c("hour", "night", "pet"
), row.names = c(NA, 5L), class = "data.frame")

structure(list(hour = structure(c(1123624800, 1123628400, 1123632000, 
1123635600, 1123639200), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    night = c(FALSE, FALSE, TRUE, TRUE, TRUE), pet = c(TRUE, 
    TRUE, TRUE, TRUE, TRUE), rising = c(TRUE, TRUE, FALSE, TRUE, 
    FALSE)), .Names = c("hour", "night", "pet", "rising"), row.names = c(NA, 
5L), class = "data.frame")


filters <- c("rising", "pet", "night")
match(filters, names(df))[!is.na(match(filters, names(df)))]

如果我要明确写出我希望代码做什么:

return(df1[df1$night & df1$pet, ]) 
return(df2[df2$night & df2$pet $ df2$rising, ])

编辑:我将重写它以希望更清楚。 我有一个数据框,其中最多包含三个逻辑向量,其中包含各种数据质量过滤器的标志。例如,三个潜在向量的名称是“夜”、“宠物”、“上升”。数据框将具有这些向量中的 1 到 3 个的某种组合。有时它会有“pet”和“night”,或者“night”和“rising”,或者“pet”和“rising”,或者三者兼有....

我想返回所有现有逻辑向量都为真的记录。问题是我事先不知道存在哪些向量(这取决于函数调用中的选项),所以我想编写代码以能够处理所有各种组合。比如:

check which logical vectors exist
return(df[(all existing vectors are true), ]

如果我只是尝试

return(df[df$rising & df$pet $ df$night, ]) 

只要其中一列丢失,代码就会失败,因此我需要一种更强大的方法来完成此操作。

希望这更清楚!一般来说,如果我不能清楚地表达问题,那就意味着我在做一些愚蠢的事情......

【问题讨论】:

  • 假设第二个structuredf2,您想构建一个新的data.frame,它将来自其他两个数据帧中匹配列的所有值组合起来(如果是这样,对NA 可能产生的结果有什么要求?或者,您想要一个组合向量的命名列表吗?您想要的结果样本会有所帮助。

标签: r filter dataframe


【解决方案1】:

更新:

df2[Reduce(`&`, df2[sapply(df2, is.logical)]),]

将返回所有逻辑列都是TRUE 的行。也可以使用最后介绍的apply方法。


您可以通过Reduce&amp; 实现您的目标:

df1[Reduce(`&`, df1[-1]),]
#                  hour night  pet
# 3 2005-08-10 00:00:00  TRUE TRUE
# 4 2005-08-10 01:00:00  TRUE TRUE
# 5 2005-08-10 02:00:00  TRUE TRUE

上面我们排除了带有-1 的第一列。下面我们使用您在filters 中定义的列列表:

df2[Reduce(`&`, df2[filters]),]
#                  hour night  pet rising
# 4 2005-08-10 01:00:00  TRUE TRUE   TRUE 

Reduce 迭代地将&amp; 应用于其第二个参数中的元素对(数据框中的列)。

或者,您可以使用apply

df2[apply(df2[filters], 1, all),]
df1[apply(df1[-1], 1, all),]

【讨论】:

  • 第一个解决方案(不包括第一列)有效,但我无法让第二个解决方案有效。但是,由于这将是用户调用的函数,我希望有一种更可靠的方法来识别现有列。我已经编辑了我的问题以更清楚。感谢您的帮助!
  • @IcebergSlim,您能否更清楚地说明第二个不起作用的意思?它是如何失败的?您确定您使用的df2filters 变量与您的问题中的dputs 完全相同吗?我建议您清除工作区并重新创建 df2filter
  • @IcebergSlim,查看更新的答案以解决您的编辑问题。
  • 谢谢,这行得通。如果用户传递给函数的 df 中已经有逻辑,那可能是个问题,但我会在函数顶部进行检查。再次感谢,
猜你喜欢
  • 2015-02-17
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 2021-01-14
  • 2021-11-18
  • 2023-01-27
  • 2019-05-21
相关资源
最近更新 更多