3

给定一个如下所示的虚拟数据框:

Data1<-rnorm(20, mean=20)
Data2<-rnorm(20, mean=21)
Data3<-rnorm(20, mean=22)
Data4<-rnorm(20, mean=19)
Data5<-rnorm(20, mean=20)
Data6<-rnorm(20, mean=23)
Data7<-rnorm(20, mean=21)
Data8<-rnorm(20, mean=25)
Index<-rnorm(20,mean=5)

DF<-data.frame(Data1,Data2,Data3,Data4,Data5,Data6,Data7,Data8,Index)

我想做的是根据索引列删除(使 NA)每行的某些列。我走了很长一段路,这样做是为了让您了解我正在尝试做的事情:

DF[DF$Index>5.0,8]<-NA
DF[DF$Index>=4.5 & DF$Index<=5.0,7:8]<-NA
DF[DF$Index>=4.0 & DF$Index<=4.5,6:8]<-NA
DF[DF$Index>=3.5 & DF$Index<=4.0,5:8]<-NA
DF[DF$Index>=3.0 & DF$Index<=3.5,4:8]<-NA
DF[DF$Index>=2.5 & DF$Index<=3.0,3:8]<-NA
DF[DF$Index>=2.0 & DF$Index<=2.5,2:8]<-NA
DF[DF$Index<=2.0,1:8]<-NA

这工作正常,但不是很适应。如果列数发生变化,或者我需要调整条件语句,那么重写整个代码会很痛苦(实际数据集要大得多)。

我想做的是能够定义一些变量,然后运行某种循环或应用来完全按照上面的代码行所做的。

例如,为了复制我的长代码,类似于这种逻辑:

NumCol<-8
Max<-5
Min<-2.0

if index > Max, then drop NumCol
if index >= (Max-0.5) & <=Max, than drop NumCol:(NumCol -1)

repeat until reach Min

我不知道这是否是 R 中最合乎逻辑的推理方式,而且我对循环和应用程序非常糟糕,所以我愿意接受任何可以复制上述长行代码并能够调整上述变量。

4

2 回答 2

4

如果您不介意将 data.frame 更改为矩阵,这里有一个使用矩阵索引的解决方案。要删除的两列索引矩阵的构建是apply对函数族的一个很好的回顾:

Seq      <- seq(Min, Max, by = 0.5)
col.idx  <- lapply(findInterval(DF$Index, Seq) + 1, seq, to = NumCol)
row.idx  <- mapply(rep, seq_along(col.idx), sapply(col.idx, length))
drop.idx <- as.matrix(data.frame(unlist(row.idx), unlist(col.idx)))

M <- as.matrix(DF)
M[drop.idx] <- NA
于 2012-11-09T02:08:31.970 回答
1

这是一个内存高效(但我不能声称优雅)的 data.table 解决方案

它使用非常有用的函数findInterval来改变你小于/大于循环

# 
library(data.table)
DT <- data.table(DF)
# create an index column which 1:8 represent your greater than less than
DT[,IND := findInterval(Index, c(-Inf, seq(2,5,by =0.5 ), Inf))]

# the columns you want to change
changing <- names(DT)[1:8]


setkey(DT, IND)
# loop through the indexes and alter by reference
for(.ind in DT[,unique(IND)]){
   # the columns you want to change
   .which <- tail(changing, .ind)
   # create a call to `:=`(a = as(NA, class(a), b= as(NA, class(b))
   pairlist <- mapply(sprintf, .which, .which, MoreArgs = list(fmt =  '%s = as(NA,class(%s))'))
   char_exp <- sprintf('`:=`( %s )',paste(pairlist, collapse = ','))  
 .e <- parse(text = char_exp)
  DT[J(.ind), eval(.e)]

}
于 2012-11-09T02:14:27.577 回答