【问题标题】:Subsetting data by condition按条件对数据进行子集化
【发布时间】:2012-04-27 09:33:03
【问题描述】:

我正在尝试重塑/减少我的数据。到目前为止,我使用了for 循环(非常慢),但据我所知,Plyr 应该很快。

我有很多组(公司,作为数据集中的一个因素),我想完全删除所有在该公司的任何单元格中显示 value 为 0 条目的公司。因此,我创建了一个新的data.frame,但在某些时候忽略了所有为value 显示0 的组。

forloop:

Data Creation:

set.seed(1) 
mydf <- data.frame(firmname = sample(LETTERS[1:5], 40, replace = TRUE), 
        value = rpois(40, 2))

-----------------------------
splitby = mydf$firmname


new.data <- data.frame()

for (i in 1:(length(unique(splitby)))) {
temp <- subset(mydf, splitby == as.character(paste(unique(splitby)[i]))) 
    if (all(temp$value > 0) == "TRUE") {     
    new.data <- rbind(new.data, temp) 
} 
} 

Delete all empty firm factors 
new.data$splitby <- factor(new.data$splitby)

有没有办法通过plyr 包实现这一目标? subset 函数可以在那种情况下使用吗?

编辑为了重现问题,添加了 BenBarnes 建议的数据创建。本,非常感谢。此外,我的代码已更改,以符合下面提供的答案。

【问题讨论】:

  • 您不提供样本数据,但这听起来像是使用[ 运算符的标准子集。
  • @Andrie 在我看来,他想删除一个组中的所有条目,其中任何条目都符合某些条件。所以plyrby 似乎更容易。 Jan,请阅读此内容,因为它将帮助我们解决您的问题:stackoverflow.com/questions/5963269/…
  • 非常感谢您的回答!我按照 Ben 的建议编辑了帖子并添加了数据复制(见下文)。
  • @Andrie:非常感谢!标准子集实际上是我需要的。计算上,我的 for 循环需要 122 秒,而我的小测试数据集(~55k 观察),Plyr 17 秒和 [] 操作仅 0.07!

标签: r split subset plyr


【解决方案1】:

您可以为ddply() 中的.fun 参数提供一个匿名函数:

set.seed(1)

mydf <- data.frame(firmname = sample(LETTERS[1:5], 40, replace = TRUE),
  value = rpois(40, 2))

library(plyr)

ddply(mydf,.(firmname), function(x) if(any(x$value==0)) NULL else x )

或者使用 [,正如 Andrie 所建议的那样:

firms0 <- unique(mydf$firmname[which(mydf$value == 0)])

mydf[-which(mydf$firmname %in% firms0), ]

注意ddply的结果是按照firmname排序的

编辑

对于您的 cmets 中的示例,这种方法再次比使用 ddply() 进行子集更快,只选择具有三个以上条目的公司:

firmTable <- table(mydf$firmname)

firmsGT3 <- names(firmTable)[firmTable > 3]

mydf[mydf$firmname %in% firmsGT3, ]

【讨论】:

  • 嗨,Ben,感谢您提供这些出色的答案!这正是我想要的。我不知道如何在整个组上应用第二个版本([ 操作)。正如上面进一步的评论中所写,[ 操作比 Plyr 或 for 循环快得多。
  • 第二个答案在调节单个单元格值时效果很好。在以行数为条件时它也可以工作吗?我尝试了 Plyr:mydf &lt;- ddply(mydf,.(firmname), function(x) if(length(x$firmname &lt; 3 )) NULL else x ) 和许多其他使用 [ 方法的方法,但无法让它发挥作用。
  • 我让它工作了! ddply(mydf, .(firmname), function(x) if(length(x$firmname) &gt; 3) NULL else x ) 正在做这项工作。这将选择具有超过 3 个观察值的所有组(公司)。使用&lt; 整理此数据。我想这只是一个) 太多了。
  • @Jan,感谢您提出有趣的附加问题,并且很好地解决了这个问题!我已编辑我的答案以包含一个替代解决方案,该解决方案似乎比您使用 ddply() 的解决方案更快。
猜你喜欢
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 2022-06-18
  • 1970-01-01
  • 2022-09-29
  • 2020-04-15
  • 2016-08-08
  • 1970-01-01
相关资源
最近更新 更多