繁体   English   中英

基于多个条件的数据帧子集

[英]subset of data frame on based on multiple conditions

我实际上在代码的特定任务上遇到了麻烦。 我有一个数据框

n  <- 6
set.seed(123)
df <- data.frame(x=paste0("x",seq_along(1:n)), A=sample(c(-2:2),n,replace=TRUE), B=sample(c(-1:3),n,replace=TRUE))
#
#    x  A B
# 1 x1 -1 1
# 2 x2  1 3
# 3 x3  0 1
# 4 x4  2 1
# 5 x5  2 3
# 6 x6 -2 1

还有一个决策树

A>0;Y;Y;N;N
B>1;Y;N;Y;N
C;1;2;2;1

我加载

dt <- read.csv2("tmp.csv", header=FALSE)

我想为(A> 0)和(B> 1)的所有可能组合创建一个循环,并将C值设置为满足该条件的x子集。 所以,这就是我所做的

nr <- 3
nc <- 5

cond <- dt[1:(nr-1),1,drop=FALSE]
rule <- dt[nr,1,drop=FALSE]

subdf <- vector(mode="list",2^(nr-1))

for (i in 2:nc) {
  check <- paste0("")
  for (j in 1:(nr-1)) {
    case <- paste0(dt[j,1])
    if (dt[j,i]=="N")
      case <- paste0("!",case)
    check <- paste0(check, "(", case, ")" )

    if (j<(nr-1))
      check <- paste0(check, "&")

  }

  subdf[i]   <- subset(df,check)
  subdf[i]$C <- dt[nr,i]

}
unlist(subdf)

不幸的是,使用子集时出现错误,因为它无法解析我的字符串语句中的条件。 我该怎么办?

您的问题是创建子集:subset命令需要一个布尔值,并且给了它一个字符串。 ('校验')。 因此,这里最简单的解决方案是添加“解析”。 我觉得有一种解决此问题的更优雅的方法,希望有人能做得到,但是您可以使用以下方法修复代码的最后一部分

 mysubset  <- subset(df,with(df,eval(parse(text=check))))
  if(nrow(mysubset)>0){
    mysubset$C <-  dt[nr,i]
  } 
  subdf[[i]]<-mysubset

我已经添加了parse / eval部分来生成布尔向量,以仅对“ TRUE”情况进行子集化,并添加了是否可以添加C的检查(如果没有行,则会出错)。

基于先前的答案,我想出了一种更优雅/更实用的方法来生成组合规则的向量,然后使用apply / lapply将它们全部应用于数据。

##create list of formatted rules

#format each 'building' block separately, 
#based on rows in 'dt'.
part_conditions <- apply(dt[-nrow(dt),],MARGIN=1,FUN=function(x){
  res <- sprintf("(%s%s)", ifelse(x[-1]=="Y","","!"), x[1])
})

# > part_conditions
# 1        2       
# [1,] "(A>0)"  "(B>1)" 
# [2,] "(A>0)"  "(!B>1)"
# [3,] "(!A>0)" "(B>1)" 
# [4,] "(!A>0)" "(!B>1)"

#combine to vector of conditions
conditions <- apply(part_conditions, MARGIN=1,FUN=paste, collapse="&")

# > conditions
# [1] "(A>0)&(B>1)"   "(A>0)&(!B>1)"  "(!A>0)&(B>1)"  "(!A>0)&(!B>1)"

#for each condition, test in data wheter condition is 'T'
temp <- sapply(conditions, function(rule){
  return(with(df, eval(parse(text=rule))))
}
)


rules <- as.numeric(t(dt[nrow(dt),-1]))

#then find which of the (in this case) four is 'T', and put the appropriate rule
#in df
df$C <- rules[apply(temp,1,which)]
> df
   x  A B C
1 x1 -1 1 1
2 x2  1 3 1
3 x3  0 1 1
4 x4  2 1 2
5 x5  2 3 1
6 x6 -2 1 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM