使用NA删除基于表格的过滤器

时间:2019-03-12 14:52:13

标签: r data.table

我正在将数据行分配给几个不同的组。主要问题是有许多组,但不是每个组都使用相同的字段集。我想建立一个可以遍历或推过一个函数的参考表,但是我不知道如何从不需要的过滤器中删除这些字段。

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

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"))

2 个答案:

答案 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{
    }
    }
相关问题