【问题标题】:R data.table: Filter for rows by condition in multiple variablesR data.table:在多个变量中按条件过滤行
【发布时间】:2018-11-20 18:22:23
【问题描述】:

我对以下 data.table 有过滤问题,真的希望有人能帮助我解决这个问题。我不确定是否有一种简单的方法可以做到这一点,并希望要求不要太多。所以这是我的问题:

A   B   C   Area
aa  M+H 1   127427
aa  M+H 2   204051.5
aa  M+Na    1   6855539.48777
aa  M+Na    2   6469689
bb  M+H 1   15330650
bb  M+H 2   214221
bb  M+H 3   11357158
bb  M+K 1   2140221
bb  M+K 2   61715568

对于每组 A B (aa M+H, aa M+Na, bb M+H, bb M+K) 值 C > 1 的所有行,如果其面积值高于该行中的值,则应过滤掉具有相同的 A B 组合和 C 值为 1(每个 A B C 组合在表中仅存在一次)。在该步骤之后,应保留以下行:

A   B   C   Area
aa  M+H 1   127427
aa  M+Na    1   6855539.48777
aa  M+Na    2   6469689
bb  M+H 1   15330650
bb  M+H 2   214221
bb  M+H 3   11357158
bb  M+K 1   2140221

然后我想过滤掉所有在同一个 A C 组(aa 1、aa 2、bb 1、bb2)但面积值高于“M+H”行的行作为 B 值。所以应该留下:

A   B   C   Area
aa  M+H 1   127427
aa  M+Na    2   6469689
bb  M+H 1   15330650
bb  M+H 2   214221
bb  M+H 3   11357158
bb  M+K 1   2140221

最后去掉 C 中没有一行值为 1 的所有 A B 组(aa M+H、aa M+Na、bb M+H、bb M+K)。所以应该只有:

A   B   C   Area
aa  M+H 1   127427
bb  M+H 1   15330650
bb  M+H 2   214221
bb  M+H 3   11357158
bb  M+K 1   2140221

我试图使用 data.table 来完成它,但如果有人告诉我 dplyr 更适合它,我也会很高兴有一个解决方案。无论如何,非常感谢您的时间和精力!

亚塞尔

【问题讨论】:

  • 你能澄清一下过滤掉第一个表的规则吗?为什么bb M+H 2 214221 没有被过滤掉?是的,dplyr 非常适合这项任务
  • 这里有一些东西可以帮助您入门:DT[, .SD[!(C>1 & Area > Area[C==1])], by=.(A, B)][, .SD[Area<=Area[B=="M+H"]], by=.(A, C)]

标签: r data.table


【解决方案1】:

欢迎来到 SO!

按照您的指示,我将得出与您不同的结果,但您可以根据自己的需要进行调整:

library(data.table)

DT <- data.table(stringsAsFactors=FALSE,
                 A = c("aa", "aa", "aa", "aa", "bb", "bb", "bb", "bb", "bb"),
                 B = c("M+H", "M+H", "M+Na", "M+Na", "M+H", "M+H", "M+H", "M+K",
                       "M+K"),
                 C = c(1L, 2L, 1L, 2L, 1L, 2L, 3L, 1L, 2L),
                 Area = c(127427, 204051.5, 6855539.48777, 6469689, 15330650, 214221,
                          11357158, 2140221, 61715568)
)

DT <- DT[DT[C==1], on=.(A, B)][i.Area-Area > 0 | C==1]
DT[, c("i.C", "i.Area") := NULL]

DT <- DT[DT[B=="M+H"], on=.(A, C)][i.Area-Area <= 0]
DT[, c("i.B", "i.Area") := NULL]

DT <- DT[DT[C==1], on=.(A, B)]
DT[, c("i.C", "i.Area") := NULL]

【讨论】:

  • 非常感谢您的帮助!你是对的,我在我的例子中犯了一个错误,(我在写它的时候已经在抽烟了)。我现在以正确的方式进行了编辑。对于第二个条件,我还必须用“更高”替换“更低”。明天一回到我的主计算机,我将立即测试解决方案!
【解决方案2】:

这不是最迷人的解决方案,但它的一些变体可能会让你到达那里:

library(data.table)

A <- c(rep("aa",4),rep("bb",5))
B <- c(rep("M+H",2),rep("M+Na",2),rep("M+H",3),rep("M+K",2))
C <- c(1,2,1,2,1,2,3,1,2)
Area <- c(127427,204051.5,6855539.48777,6469689,15330650,214221,11357158,2140221,61715568)
DT <- as.data.table(cbind(A,B,C,Area))

DT <- setorder(DT,A,B)
DT$ABFilter <- sapply(1:nrow(DT), function(x) ifelse((C[x]==1 
      || (C[x]==2 && A[x]==A[x-1] && B[x]==B[x-1] && (Area[x] < Area[x-1]))
      || (C[x]==3 && A[x]==A[x-2] && B[x]==B[x-2] && (Area[x] < Area[x-2])))
      , "Keep", "Discard"))
DT <- DT[ABFilter=="Keep",]
DT$ABFilter <- NULL
DT

DT <- setorder(DT,A,C)
DT$ACFilter <- sapply(1:nrow(DT), function(x) ifelse((B[x]=="M+H" 
      || (B[x]!="M+H" && A[x]==A[x-1] && C[x]==C[x-1] && B[x-1]=="M+H" && (Area[x] < Area[x-1]))
      || (B[x]!="M+H" && A[x]==A[x-2] && C[x]==C[x-2] && B[x-2]=="M+H" && (Area[x] < Area[x-2])))
      , "Keep", "Discard"))
DT <- DT[ACFilter=="Keep",]
DT$ACFilter <- NULL
DT

DT <- setorder(DT,A,B,C)
DT$ABCFilter <- sapply(1:nrow(DT), function(x) ifelse(C[x]==1 
      || (C[x]==2 && A[x]==A[x-1] && B[x]==B[x-1] && C[x-1]==1) 
      || (C[x]==3 && A[x]==A[x-1] && B[x]==B[x-1] && C[x-1]==1) 
      || (C[x]==3 && A[x]==A[x-2] && B[x]==B[x-2] && C[x-2]==1)
      , "Keep", "Discard"))
DT <- DT[ABCFilter=="Keep",]
DT$ABCFilter <- NULL
DT

我也不太清楚您使用的规则。看起来 Area = 11357158 的行应该被保留,因为它小于 C = 1 的相应行,而 Area = 6855539.48777 的行应该被保留,因为它大于 B = M+H 的相应行:

    A    B C          Area
1: aa  M+H 1        127427
2: aa M+Na 1 6855539.48777
3: aa M+Na 2       6469689
4: bb  M+H 1      15330650
5: bb  M+H 2        214221
6: bb  M+H 3      11357158
7: bb  M+K 1       2140221

【讨论】:

  • 非常感谢您的帮助!你是对的,我在我的例子中犯了一个错误,(我在写它的时候已经在抽烟了)。我现在以正确的方式进行了编辑。对于第二个条件,我还必须用“更高”替换“更低”。明天一回到我的主计算机,我将立即测试解决方案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 2020-09-01
  • 2015-06-12
  • 1970-01-01
  • 2022-01-11
  • 2021-11-25
相关资源
最近更新 更多