我对以下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
对于每个AB组(aa M + H,aa M + Na,bb M + H,bb M + K),如果其Area值大于行中的所有行,则应滤除C> 1的所有行具有相同的AB组合和C值1(每个ABC组合在表中仅存在一次)。在该步骤之后,应保留以下行:
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
之后,我想过滤出同一AC组中的所有行(aa 1,aa 2,bb 1,bb2),但是Area值比带有“ 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
最后,将所有剩下的A B组(aa M + H,aa M + Na,bb M + H,bb M + K)除掉,剩下的C行中的值都不为1。因此应该只有:
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更好,我也会为那里的解决方案感到高兴。无论如何,非常感谢您的时间和精力!
Yasel
答案 0 :(得分:2)
欢迎您!
按照您的指示,我得到的结果与您的不同,但是您也许可以根据需要进行调整:
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]
答案 1 :(得分:1)
这不是最吸引人的解决方案,但是它的某些变化可能会带您到达那里:
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