【问题标题】:Is there a way to subset a group if ONLY the first observation meets a criteria?如果只有第一个观察符合标准,有没有办法对一个组进行子集化?
【发布时间】:2019-10-01 07:29:24
【问题描述】:

我有一个像这样的数据框:

ID = c(1,1,1,2,2,2,3,3,3,4,4,4,4)
VAR_1 = c(2,4,6,1,7,9,4,4,3,1,7,4,0)
VAR_2 = c(NA,NA,NA,NA,NA,20190101,20190101,20190101,NA,20190101,NA,NA,NA)
df2 = data.frame(ID,VAR_1,VAR_2)

如果 VAR_2 中按组的第一个观察值有值,我想从这个数据框中子集每个组 (ID) 的所有行,在这个简单的情况下,新的子集应该是 ID 3 和 4 中的所有行

为了更好地表达这一点:

df                                       df_subset   

ID VAR_1 VAR_2                           ID VAR_1 VAR_2
1   2     NA                             3   4     20190101                           
1   4     NA                             3   4     20190101
1   6     NA                             3   3     NA
2   1     NA                             4   1     20190101
2   7     NA                             4   7     NA
2   9     20190101                       4   4     NA
3   4     20190101                       4   0     NA
3   4     20190101
3   3     NA
4   1     20190101
4   7     NA
4   4     NA
4   0     NA

我设法通过几个步骤来做到这一点(我将原始数据子集仅按组进行第一次观察,为 VAR_1 分配一个特殊值,重新合并,然后最后按特殊值过滤),但我想知道是否有一种更简单更优雅(并且可能)更有效的方法。我不需要 VAR_1,因此可以根据需要对其进行更改以提供更快的解决方案。

任何帮助将不胜感激。

【问题讨论】:

  • 去除所有 NA 值的 df2[!is.na(df2$VAR_2),] 怎么样?

标签: r group-by dplyr conditional-statements


【解决方案1】:

使用dplyr,我们可以group_by ID 并且仅当每个组中的第一个值是非NA 时才选择组。

library(dplyr)

df2 %>%
  group_by(ID) %>%
  filter(!is.na(VAR_2[1L]))

#     ID VAR_1    VAR_2
#  <dbl> <dbl>    <dbl>
#1     3     4 20190101
#2     3     4 20190101
#3     3     3       NA
#4     4     1 20190101
#5     4     7       NA
#6     4     4       NA
#7     4     0       NA

提取第一个值的一些变体可能是(感谢@tmfmnk)

df2 %>%  group_by(ID) %>% filter(!is.na(first(VAR_2)))

df2 %>% group_by(ID) %>%  filter(!is.na(nth(VAR_2, 1)))

同样使用基础 R ave

df2[with(df2, ave(!is.na(VAR_2), ID, FUN = function(x) x[1L])), ]

或者有点复杂的splitsubset

subset(df2, ID %in% names(na.omit(sapply(split(df2$VAR_2, df2$ID), head, 1))))

【讨论】:

  • df2 %&gt;% group_by(ID) %&gt;% filter(!is.na(first(VAR_2))) 也可以。
猜你喜欢
  • 2017-01-12
  • 1970-01-01
  • 1970-01-01
  • 2020-12-16
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多