【问题标题】:How to conditionally select all elements of a data.frame that match a number of factors如何有条件地选择与多个因素匹配的 data.frame 的所有元素
【发布时间】:2012-06-06 07:15:23
【问题描述】:

我必须根据特定条件从数据框中选择一堆数据。数据框大致如下:

  F1 F2 D1 D2
1 A1 B1  1  0
2 A1 B1  1  1
3 A1 B1  0  0
4 A1 B2  1  0
5 A1 B2  0  0
6 A2 B2  1  0
7 A2 B2  1  1

Fx 是因子,Dx 是数据值。我要做的是:

  1. 查找数据值与特定模式匹配的行。
  2. 对于与该模式匹配的每一行,查找具有相同因子的所有行
  3. 对于每个唯一的因子组合,对具有该组合的所有行应用一些操作

例如,

factors <- unique(data[D1==1 & D2 == 1, c("F1","F2")])

会给我第 1 步和第 2 步的大部分内容。

还有

data[data$F1 %in% factors$F1 & data$F2 %in% factors%F2,]

我越来越接近解决方案,但使用上面的示例数据,这将选择所有行。但不应选择第 4 行和第 5 行,因为它们不是完全匹配的。如何添加某种要求 %in% 匹配发生在同一行的条件?

我觉得这应该是一个常见的操作,因此 R 可能有一个聪明的方法来做到这一点。

有什么想法吗???谢谢。

【问题讨论】:

  • 了解plyr 包 - 这将使您的大部分分析变得非常容易。

标签: r dataframe data.table


【解决方案1】:

您可以使用data.table 包的索引来选择所有必须操作的行。

data <- data.table(data,key="F1,F2")
data[unique(data[D1 == 1 & D2 == 1,list(F1,F2)])]

【讨论】:

  • 谢谢。这似乎是在复制我已经拥有的东西。但我是,但我还不确定如何从那里移动。我想 data.table 文档会帮助我。
  • 谢谢,想通了。这似乎是最简单的解决方案。
【解决方案2】:

感觉像是 tapplypaste 的工作......例如,让我们将 data2 定义为与您的数据对象相同但具有“Val”列(您不说您是哪种行操作)可能想这样做,所以这只是为了帮助说明)...

  F1 F2 D1 D2 D3 D4 Val
1 A1 B1  1  1  0  1   7
2 A1 B1  1  0  1  1  19
3 A2 B1  1  1  1  1  43

现在查看以下命令:

tapply(data2$Val,paste(data2$F1,data2$F2,sep="~"),sum)

你应该得到这个输出:

A1~B1 A2~B1 
   26    43 

应该清楚的是,R 正在为 F1 和 F2 的每个可能组合计算 Val 的总和(实际上,正如命令所示,它查看 F1 和 F2 的粘贴,这相当于同一件事)......对于 A1~B1,总和是 26 (7 + 19),对于 A2~B1,总和是 43(只有一个这样的行)。在tapply中将sum改成length,你会得到这样的行数,以此类推。

希望这会有所帮助... :)

编辑:刚刚看到你的修改。如果您只是在数据中 F1 和 F2 的组合是因子对象中列出的 F1 和 F2 组合之一的所有行之后...您可以使用paste

data[paste(data$F1,data$F2,sep="~") %in% paste(factors$F1,factors$F2,sep="~"),]

sep="~" 不是绝对需要的,只是习惯的力量。上面的行应该给你我认为你想要的行。如果您想对具有特定 F1/F2 组合的行的每个子集执行一个函数,请使用上述的 tapply :)


为方便起见,data2的dput如下:

structure(list(
F1 = structure(c(1L, 1L, 2L), .Label = c("A1", "A2"), class = "factor"), 
F2 = structure(c(1L, 1L, 1L), .Label = "B1", class = "factor"), 
D1 = c(1L, 1L, 1L), D2 = c(1L, 0L, 1L), D3 = c(0L, 1L, 1L), 
D4 = c(1L, 1L, 1L), Val = c(7, 19, 43)), 
.Names = c("F1", "F2", "D1", "D2", "D3", "D4", "Val"), 
row.names = c(NA, -3L), class = "data.frame")

【讨论】:

  • 首先查看我提出的解决方案的“编辑”部分......它应该有望解决您的问题:)
猜你喜欢
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 2011-05-27
  • 2017-07-23
  • 2013-02-22
  • 1970-01-01
相关资源
最近更新 更多