r语言 - 删除基于 NA 表的过滤器



我正在将数据行分配给几个不同的组。 主要问题是有许多组,但并非每个组都使用相同的字段集。 我想设置一个引用表,我可以循环或推过一个函数,但我不知道如何从过滤器中删除不需要的字段。

下面是示例代码,我提供了当前解决方案的一个版本以及一个示例表。

library(data.table)
set.seed(1)
n <- 1000
#Sample Data
ExampleData <- data.table(sample(1:3,n,replace = TRUE),
sample(10:12,n,replace = TRUE),
sample(letters[1:3],n,replace = TRUE),
sample(LETTERS[1:3],n,replace = TRUE))
#Current solution
ExampleData[V1 == 1 & V2 == 11 & V4 == "C", Group := "Group1"]
ExampleData[V1 == 2, Group := "Group2"]
ExampleData[V1 == 3 & V3 == "a" & V4 == "B", Group := "Group3"]

#Example reference table
ExampleRefTable <- data.table(Group = c("Group1","Group2","Group3"),
V1 = c(1,2,3),
V2 = c(11,NA,NA),
V3 = c(NA,NA,"a"),
V4 = c("C",NA,"B"))

(感谢@eddi:) 您可以使用by=遍历 ref 表中的行/组:

ExampleRefTable[, 
ExampleData[copy(.SD), on = names(.SD)[!is.na(.SD)], grp := .BY$Group]
, by = Group] 

对于每个组,我们使用.SD(ref 表的其余SubsetData)进行更新连接,忽略 NA 的.SD列。.BY包含by=的每个组值。


(我最初的答案:) 您可以将 ref 表拆分为具有非 NA 值的子集:

ExampleRefTable[, gNA := .GRP, by=ExampleRefTable[, !"Group"]]
RefTabs = lapply(
split(ExampleRefTable, by="gNA", keep.by = FALSE), 
FUN = Filter, f = function(x) !anyNA(x)
)

看起来像

$`1`
Group V1 V2 V4
1: Group1  1 11  C
$`2`
Group V1
1: Group2  2
$`3`
Group V1 V3 V4
1: Group3  3  a  B

然后使用更新联接循环访问这些表:

ExampleData[, Group := NA_character_]
for (i in seq_along(RefTabs)){
RTi = RefTabs[[i]]
nmi = setdiff(names(RTi), "Group")
ExampleData[is.na(Group), Group := 
RTi[copy(.SD), on=names(.SD), x.Group]
, .SDcols=nmi][]
} 
rm(RTi, nmi)

通过过滤is.na(Group),我假设 ref 表中的规则是互斥的。

由于未解决的问题,需要.SD上的copy

如果有许多组共享相同的缺失/非缺失列,这可能比@eddi的方式(在此答案的顶部)更有效。


如果您正在手动编写参考表,我建议...

rbindlist(idcol = "Group", fill = TRUE, list(
NULL = list(V1 = numeric(), V2 = numeric(), V3 = character(), V4 = character()),
Group1 = list(V1 = 1, V2 = 11, V4 = "C"),
Group2 = list(V1 = 2),
Group3 = list(V1 = 3, V3 = "a", V4 = "B")
))

Group V1 V2   V3   V4
1: Group1  1 11 <NA>    C
2: Group2  2 NA <NA> <NA>
3: Group3  3 NA    a    B

以便于阅读和编辑。

如果条件正确,我们可以遍历参考数据框并将其与示例数据分配组进行比较,这可以使用任何大小的参考表和数据进行缩放,尽管如果数据>~100k,您可能希望对某些内容进行矢量化:

lenC<-ncol(ExampleRefTable)
lenT<-nrow(ExampleRefTable)
lenDat<-nrow(ExampleData)
ExampleData$Group<-"NA"
for(i in 1:lenT){
iter=i
Group_Assign<-ExampleRefTable[i,1]
Vals<-ExampleRefTable[iter,2:lenC]
for(i in 1:lenDat){
LogicArray<-ExampleData[i,1:4]==Vals
if(all(LogicArray, na.rm=T)==T){
ExampleData[i]$Group<-Group_Assign
}else{
}
}
}
> ExampleData
V1 V2 V3 V4  Group
1:  1 11  c  C Group1
2:  2 12  c  B Group2
3:  2 11  c  A Group2
4:  3 12  b  B     NA
5:  1 10  a  C     NA
---                   
996:  3 12  a  B Group3
997:  2 10  a  C Group2
998:  1 10  a  A     NA
999:  1 10  a  B     NA
1000:  1 11  b  C Group1

此示例假设参考数据中的 NA 可以与示例数据中的任何值匹配,只要位置正确,例如:

#This is assigned Group1 since NA in the ref.table matched c in pos.3
> ExampleRefTable 
V1 V2 V3 V4  Group 
1:  1 11 NA  C Group1
> ExampleData
V1 V2 V3 V4  Group
1:  1 11  c  C Group1 

如果 NA 应该仅与 NA 值匹配(示例数据中没有这些值),您将更改以下代码:

for(i in 1:lenDat){
LogicArray<-ExampleData[i,1:4]==Vals
A<-Vals
B<-ExampleData[i,1:4]
NAA<-is.na(A)
NAB<-is.na(B)
if(all(NAA==NAB)==T && all(LogicArray, na.rm=T)==T){
ExampleData[i]$Group<-Group_Assign
}else{
}
}

最新更新