【问题标题】:How can I drop observations within a group following the occurrence of NA?NA 发生后如何在组内删除观察结果?
【发布时间】:2016-06-15 21:48:47
【问题描述】:

我正在尝试清理我的数据。标准之一是我需要一个不间断的变量“资产”序列,但我有一些 NA。但是,我不能简单地删除 NA 观察,而是需要删除 NA 事件之后的所有后续观察。

这里是一个例子:

productreference<-c(1,1,1,1,2,2,2,3,3,3,3,4,4,4,5,5,5,5)
Year<-c(2000,2001,2002,2003,1999,2000,2001,2005,2006,2007,2008,1998,1999,2000,2000,2001,2002,2003)
assets<-c(2,3,NA,2,34,NA,45,1,23,34,56,56,67,23,23,NA,14,NA)
mydf<-data.frame(productreference,Year,assets)
mydf

#    productreference Year assets
# 1                 1 2000      2
# 2                 1 2001      3
# 3                 1 2002     NA
# 4                 1 2003      2
# 5                 2 1999     34
# 6                 2 2000     NA
# 7                 2 2001     45
# 8                 3 2005      1
# 9                 3 2006     23
# 10                3 2007     34
# 11                3 2008     56
# 12                4 1998     56
# 13                4 1999     67
# 14                4 2000     23
# 15                5 2000     23
# 16                5 2001     NA
# 17                5 2002     14
# 18                5 2003     NA

我已经看到有一种方法可以使用 plyr 按组执行功能,并且我还能够创建一个包含 0-1 的列,其中 0 表示资产具有有效条目,1 突出显示缺失的值不。

mydf$missing<-ifelse(mydf$assets>=0,0,1)
mydf[c("missing")][is.na(mydf[c("missing")])] <- 1

我有一个非常大的数据集,因此无法手动删除行,非常感谢您的帮助!

【问题讨论】:

  • 您希望使用productreference 作为分组变量来完成这项工作吗?
  • 这里猜到一半了mydf[!is.na(ave(assets, productreference, FUN = cumsum)), ]
  • 既然我们有 dplyrdata.table 的答案,我会在 rawr 的评论中添加注释,说明这就是你在 base 中的做法。
  • 是的,我的意思是产品参考,而不是你。我只是尝试了这样做的“基本方式”,但我收到一个名为“交互错误(...):找不到对象'productreference'”的错误。有什么想法可能出了什么问题?

标签: r


【解决方案1】:

我相信这就是你想要的:

library(dplyr)
group_by(mydf, productreference) %>%
    filter(cumsum(is.na(assets)) == 0)
# Source: local data frame [11 x 3]
# Groups: productreference [5]
# 
#    productreference  Year assets
#               (dbl) (dbl)  (dbl)
# 1                 1  2000      2
# 2                 1  2001      3
# 3                 2  1999     34
# 4                 3  2005      1
# 5                 3  2006     23
# 6                 3  2007     34
# 7                 3  2008     56
# 8                 4  1998     56
# 9                 4  1999     67
# 10                4  2000     23
# 11                5  2000     23

【讨论】:

  • 谢谢,这看起来很有希望!不幸的是,我在这里也收到一个错误:“错误:找不到函数“%>%”。”我需要安装任何其他软件包吗?
  • 你有什么版本的dplyr%.% 在版本 0.2(2014 年 5 月)中已弃用并替换为 %&gt;%...当前版本类似于 0.4.3...
  • 我有1.8.4版本;我刚刚运行了命令“update.packages()”,但没有提供新版本的 plyr。我有什么问题还是我有最新的版本?
  • 你说plyr,我说dplyrd 很重要。 dplyr 或多或少是 plyr 的替代品。它只关注数据帧(不像 plyr 也适用于列表和数组),但效率要高得多(也更加用户友好)。
【解决方案2】:

这是使用data.table的相同方法:

library(data.table)
dt <- as.data.table(mydf)

dt[,nas:= cumsum(is.na(assets)),by="productreference"][nas==0]

#    productreference Year assets nas
# 1:                1 2000      2   0
# 2:                1 2001      3   0
# 3:                2 1999     34   0
# 4:                3 2005      1   0
# 5:                3 2006     23   0
# 6:                3 2007     34   0
# 7:                3 2008     56   0
# 8:                4 1998     56   0
# 9:                4 1999     67   0
#10:                4 2000     23   0
#11:                5 2000     23   0

【讨论】:

  • 它会为大数据集设置键。
  • 那太好了,因为我需要通过“productreference”做进一步的分析!不幸的是,我收到错误消息:“[.data.frame(small, , :=(nas, cumsum(is.na(estimatedassets))) 中的错误:未使用的参数(by = "productreference")”。这可能是因为我的产品参考类型错误?我将其作为数字导入...
  • 您需要这样做:dt &lt;- as.data.table(mydf)。您还需要加载/安装data.table 包。您收到此错误是因为您尝试在 data.frame 上使用 data.table 操作,因此您需要使用上述代码对其进行转换。
  • 我已按照您的建议转换为 data.table 并再次运行第三行。我仍然收到错误:“:=(nas, cumsum(is.na(estimatedassets))) 中的错误:检查 is.data.table(DT) == TRUE。否则,:= 和 :=(。 ..) 被定义为在 j 中使用,仅一次且以特定方式使用。”我刚刚阅读了“:=”的帮助,但仍然不明智。
  • 您的错误的快速谷歌给出了这个:stackoverflow.com/questions/27980835/…。您是否尝试在包中使用此调用?
【解决方案3】:

这是一个base R 选项

mydf[unsplit(lapply(split(mydf, mydf$productreference),
     function(x) cumsum(is.na(x$assets))==0), mydf$productreference),]    
#   productreference Year assets
#1                 1 2000      2
#2                 1 2001      3
#5                 2 1999     34
#8                 3 2005      1
#9                 3 2006     23
#10                3 2007     34
#11                3 2008     56
#12                4 1998     56
#13                4 1999     67
#14                4 2000     23
#15                5 2000     23

或者data.table的选项

library(data.table)
setDT(mydf)[, if(any(is.na(assets))) .SD[seq(which(is.na(assets))[1]-1)] 
                    else .SD, by = productreference]

【讨论】:

  • 非常感谢,这两种方法都非常有效。在 plyr 或 data.table 上使用基本 R 方法是否有任何优点或缺点?有超过 230,000 次观察,我担心运行时间......
  • 230,000 并没有那么大。 dplyr 可能会比base 快,而data.table 将是最快的。差异可能只有几秒钟——dplyrdata.table 版本之间的差异可能会更少——如果你运行它一次,这并不重要。但真正的答案是试试看!
【解决方案4】:

您可以使用基础 R 和 for 循环来实现。此代码比其他答案中的某些代码长一点。在循环中,我们通过productreferencemydf 进行子集化,并且对于每个子集,我们查找assets==NA 的第一次出现,并排除该行和所有后续行。

mydf2 <- NULL
for (i in 1:max(mydf$productreference)){
  s1 <- mydf[mydf$productreference==i,]
  s2 <- s1[1:ifelse(all(!is.na(s1$assets)), NROW(s1), min(which(is.na(s1$assets)==T))-1),]
  mydf2 <- rbind(mydf2, s2)
  mydf2 <- mydf2[!is.na(mydf2$assets),]
}
mydf2

【讨论】:

  • 谢谢,这也很好用。它确实在前几行中创建了大约 7 个额外的空观测值,但只是移动了数据框。所以事后简单地删除行也没问题。
  • 你是对的,那是因为我忘记排除 assets==NA 的行,当它们首先出现在基于产品参考的子集中时。我在上面的代码中更改了它。谢谢。
猜你喜欢
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多