我正在将数据行分配给几个不同的组。主要问题是有许多组,但不是每个组都使用相同的字段集。我想建立一个可以遍历或推过一个函数的参考表,但是我不知道如何从不需要的过滤器中删除这些字段。
下面是示例代码,我提供了当前解决方案的一个版本以及一个示例表。
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"))
答案 0 :(得分:4)
(由于@eddi :),您可以使用by=
遍历引用表中的行/组:
ExampleRefTable[,
ExampleData[copy(.SD), on = names(.SD)[!is.na(.SD)], grp := .BY$Group]
, by = Group]
对于每个组,我们使用.SD
(参考表S
ata的D
ubset的其余部分)进行更新联接,而忽略.SD
的列那是NA。 .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表中的规则是互斥的。
由于an open issue,需要copy
上的.SD
。
如果有许多组共享相同的缺失/缺失列,这可能比@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
便于阅读和编辑。
答案 1 :(得分:0)
如果条件正确,我们可以遍历参考数据帧并将其与示例数据分配组进行比较,这可以与任何大小的参考表和数据进行缩放,尽管如果数据>〜您可能希望向量化某些东西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{
}
}