如何删除R中缺少年度观察的主题?

时间:2017-05-16 15:11:20

标签: r panel-data

     num Name  year   age       X 
1      1   A   2011    68  116292
2      1   A   2012    69   46132
3      1   A   2013    70    7042
4      1   A   2014    71 -100425
5      1   A   2015    72    6493
6      2   B   2011    20   -8484
7      3   C   2015    23 -120836
8      4   D   2011     3  -26523
9      4   D   2012     4    9923
10     4   D   2013     5   82432

我有5年内各种科目代表的数据。我需要删除从2011年到2015年缺少任何年份的所有科目。我怎样才能完成它,所以在给定数据中只剩下科目A?

4 个答案:

答案 0 :(得分:2)

这是一个稍微简单明了的tidyverse解决方案。 首先,展开数据框以包含Name + year的所有组合:

df %>% complete(Name, year)

    # A tibble: 20 x 5
     Name  year   num   age       X
   <fctr> <int> <int> <int>   <int>
 1      A  2011     1    68  116292
 2      A  2012     1    69   46132
 3      A  2013     1    70    7042
 4      A  2014     1    71 -100425
 5      A  2015     1    72    6493
 6      B  2011     2    20   -8484
 7      B  2012    NA    NA      NA
 8      B  2013    NA    NA      NA
 9      B  2014    NA    NA      NA
10      B  2015    NA    NA      NA
...

然后通过“名称”将管道扩展到分组,并过滤​​以仅保留具有0个NA值的那些:

df %>% complete(Name, year) %>%
  group_by(Name) %>%
  filter(sum(is.na(age)) == 0)

# A tibble: 5 x 5
# Groups:   Name [1]
    Name  year   num   age       X
  <fctr> <int> <int> <int>   <int>
1      A  2011     1    68  116292
2      A  2012     1    69   46132
3      A  2013     1    70    7042
4      A  2014     1    71 -100425
5      A  2015     1    72    6493

答案 1 :(得分:1)

只需检查哪些名称具有正确的条目数。

## Reproduce your data
df = read.table(text="     num Name  year   age       X 
1      1   A   2011    68  116292
2      1   A   2012    69   46132
3      1   A   2013    70    7042
4      1   A   2014    71 -100425
5      1   A   2015    72    6493
6      2   B   2011    20   -8484
7      3   C   2015    23 -120836
8      4   D   2011     3  -26523
9      4   D   2012     4    9923
10     4   D   2013     5   82432",
header=TRUE)

Tab = table(df$Name)
Keepers = names(Tab)[which(Tab == 5)]
df[df$Name %in% Keepers,]
  num Name year age       X
1   1    A 2011  68  116292
2   1    A 2012  69   46132
3   1    A 2013  70    7042
4   1    A 2014  71 -100425
5   1    A 2015  72    6493

答案 2 :(得分:1)

使用data.table:

data.table解决方案可能如下所示:

library(data.table)
dt <- as.data.table(df)
dt[, keep := identical(unique(year), 2011:2015), by = Name ][keep == T, ][,keep := NULL]
#   num Name year age       X
#1:   1    A 2011  68  116292
#2:   1    A 2012  69   46132
#3:   1    A 2013  70    7042
#4:   1    A 2014  71 -100425
#5:   1    A 2015  72    6493

这更严格,因为它要求独特的年份与2011:2015完全相同。如果有2016年,例如该人将被排除在外。

限制较少的解决方案是检查2011:2015是否在您独特的年份。这应该有效:

dt[, keep := all(2011:2015 %in% unique(year)), by = Name ][keep == T, ][,keep := NULL]

因此,例如,如果A有2016年和2010年,那么它仍将保留所有A.但如果有人在2011:2015中错过了一年,则会将其排除在外。

使用基础R&amp;聚合

相同选项,但使用基础R中的aggregate

agg <- aggregate(df$year, by = list(df$Name), FUN = function(x) all(2011:2015 %in% unique(x)))
df[df$Name %in% agg[agg$x == T, 1] ,]

答案 3 :(得分:0)

使用tidyverse包时,这是一种稍微不同的方法:

library(tidyverse)

df <- read.table(text = "     num Name  year   age       X 
1      1   A   2011    68  116292
2      1   A   2012    69   46132
3      1   A   2013    70    7042
4      1   A   2014    71 -100425
5      1   A   2015    72    6493
6      2   B   2011    20   -8484
7      3   C   2015    23 -120836
8      4   D   2011     3  -26523
9      4   D   2012     4    9923
10     4   D   2013     5   82432")

df2 <- spread(data = df, key = Name, value = year)
x <- colSums(df2[, 4:7], na.rm = TRUE) > 10000
df3 <- select(df2, num, age, X, c(4:7)[x])
df4 <- na.omit(df3)

当然,所有步骤都可以构建为具有%>%运算符的单个管道。