从data.frame获取满足由R中任意数量的子条件组成的条件的行

时间:2014-04-16 14:22:01

标签: r dataframe

我有一个data.frame,可以包含N列(N在运行时定义),我想得到数据帧中满足N-1条件的行,换句话说我想只得到行前N-1列的特定值。

例如,如果我有一个包含四列(A,B,C,D)和五行的数据框:

A B C D
1 2 3 4
9 9 9 9
1 2 9 5
4 3 2 1
1 2 3 8

我会得到A == 1&的所有行B == 2& C == 3,即:

A B C D
1 2 3 4
1 2 3 8

但如上所述,数据框可以由任意数量的行和列组成(在运行时定义),条件的值可能会发生变化。

我实现了这个功能(简化):

getRows<-function(dataFrame, values) {
  conditions=rep(TRUE, dim(dataFrame)[1])
  for (k in 1:length(values)) {
    conditions=conditions&(dataFrame[,k]==values[k])
  }
  return(dataFrame[conditions,])
}

当然,这假设值向量中的值是根据数据帧的列顺序排序的,并且向量的长度是N-1。

该函数有效,但我觉得创建布尔矢量,以这种方式评估布尔表达式等等并不是很有效...特别是如果数据帧包含许多数据。

我找到的另一个解决方案是:

getRows<-function(dataFrame, values) {
  tmp=dataFrame
  for (k in 1:length(values)) {
    tmp=tmp[tmp[,k]==values[k],]
  }
  return(tmp)
}

基本上,这会通过过滤掉不满足每个条件的所有行来“减少”数据帧。但我认为这甚至是最糟糕的,因为它为每个条件创建了一个新的数据框对象(好吧总是更小,但无论如何......)。

所以我的问题是:有没有办法更有效地做到这一点?

2 个答案:

答案 0 :(得分:2)

一种可能性:

# if you are only checking for equalities
f <- function(df, values){
  # values must be a list with the columns names of df as names and the conditions
  # if you 
  y <- paste(names(values), unlist(values), sep="==", collapse=" & ")
  return(df[eval(parse(text=y), envir=df),])
  }

 l <- as.vector(1:3, "list")
 names(l) <- colnames(df)[-ncol(df)]

 f(df, l)
   A B C D
 1 1 2 3 4
 5 1 2 3 8

# you can also use other conditions
f <- function(df, values){
  # values must be a list with the columns names of df as names and the conditions
  # if you 
  y <- paste(names(values), unlist(values), collapse=" & ")
  return(df[eval(parse(text=y), envir=df),])
  }

 l <- as.vector(paste0(c("==", "<=", "=="), 1:3), "list")
 names(l) <- colnames(df)[-ncol(df)]

f(df, l)
  A B C D
1 1 2 3 4
5 1 2 3 8

答案 1 :(得分:1)

有时矩阵比data.frames更快,所以有些东西:

mat <- t(as.matrix(df[-ncol(df)))
boolMat <- (mat==values) # if necessary use match to reorder values to match columns of df
ind <- colSums(boolMat)==nrow(boolMat)
df[ind,]

我们的想法是values将沿着矩阵的列(数据帧的行)进行回收。 colSums意味着比apply更快,因此与apply(boolMat, 2, all)相比,最后一行应该稍微优化。

最佳解决方案取决于数据的大小和比例;条目是否都是整数;也许你在数据中得到的比例是多少。所以@droopy提到,你需要进行基准测试。我的方法涉及创建数据的副本,因此如果您的数据已经接近内存限制,那么它可能会很困难 - 但也许您可以生成矩阵而不是data.frame格式的数据以保存重复。