【问题标题】:R - Keep newest data that is not NA, unless only NA availableR - 保留不是 NA 的最新数据,除非只有 NA 可用
【发布时间】:2017-02-28 22:01:59
【问题描述】:

我有一个包含三列的数据集:年份、城市、值,如下所示:

year = c(2010, 2013, 2010, 2013, 2013)
city = c("Berlin","Berlin", "Munich", "Munich", "Frankfurt")
value = c(1234, NA, NA, 6372, NA)
data <- data.frame(year, value1, value2)

 year    city    value
1 2010    Berlin   1234
2 2013    Berlin     NA
3 2010    Munich     NA
4 2013    Munich   6372
5 2013 Frankfurt     NA

我想知道如何对其进行子集化,以便只保留可用的最新数据,最后我会得到如下数据:

 year    city    value
1 2010    Berlin   1234
2 2013    Munich   6372
3 2013 Frankfurt     NA

如果我在最高年份进行子集化,我会得到那一年没有数据的 NA。如果我在!is.na() 上设置子集,我会丢失所有only NA 可用的行。

我特别想做的是获取给定城市的数据最高年份,除非该城市只有 NA,然后是 NA 最高的年份。我该怎么办?

【问题讨论】:

  • 您到底想对什么进行子集化?从您的示例来看,您似乎不想对最高年份进行子集化,是否还有其他变量未在此处显示?
  • 啊,不:我想为城市列子集:给定城市数据的最高年份,除非该城市只有 NA,然后是 NA 最高的年份。是不是更清楚了?

标签: r dataframe subset na


【解决方案1】:

我们可以使用data.table。将'data.frame'转换为'data.table'(setDT(data)),按'city'分组,我们指定'i'为'year'在降序order索引,if有@987654325 @non-NA 'value',我们根据第一个non-NA 'value' 的索引对'Data.table' 进行Subset 或else 返回Data.table 的Subset。

library(data.table)
setDT(data)[order(-year), if(any(!is.na(value)))  
            .SD[which(!is.na(value))[1L]] else .SD, by = city]

或者@David Arenburg 提供的紧凑选项,我们从which.max 获取索引

setDT(data)[order(-year), .SD[which.max(!is.na(value))], by = city] 

或使用.I 进行修改以使其更快

setDT(data)[data[order(-year), .I[which.max(!is.na(value))], by = city]$V1]

【讨论】:

  • 这真是太棒了,谢谢!在我的真实数据集上尝试过,效果很好:) 不过有一个问题:如果我有多年的时间在一个有 NA 的城市(所以 2010 年,法兰克福,NA;2011 年,法兰克福,NA;2013 年,法兰克福,NA)它保留了所有这些年。我如何只保留该案例的最新年份?
  • 或者只是setDT(data)[order(-year), .SD[which.max(!is.na(value))], by = city]
  • @DavidArenburg 非常好。实际上,我正在尝试与which 类似。正在通话,所以无法专注于它
  • whichwhich.max 之间的区别在于,如果一切都是FALSEwhich 将不返回任何内容,而which.max 将返回第一行。比较 which(FALSE)which.max(FALSE)。无论哪种方式,您都可以根据需要将其添加到您的答案中
【解决方案2】:

使用dplyr 的更详细、迂回的方法。它也适用于您拥有多年 NA 的情况。

library(dplyr)
data %>%
  group_by(city) %>%
  mutate(all_na = all(is.na(value)),
         remove = ifelse(all_na,
                         year != max(year),
                         is.na(value))) %>%
  ungroup() %>%
  filter(!remove) %>%
  select(-all_na, -remove)

【讨论】:

    【解决方案3】:

    max_pos(x) 返回x 的最后一个非NA 元素在x 中的位置,或者如果没有非NA 元素,则返回x 的最后一个位置。 is_max 返回一个逻辑值,在最大位置为 TRUE,在其他位置为 FALSE。请注意,ave 将强制其结果为其第一个参数的类型,因此我们使用!! 将其转回逻辑。最后,我们对这些元素进行子集化。这假设输入按城市内的年份排序,就像问题中的情况一样。

    请注意,max_pos 是通过使用这些事实而变得紧凑的:

    • seq_along(x) * 0*x 中,0*x 是一个由零和 NA 组成的向量,因此将其与 seq_along(x) 的相应元素相加。也就是说,它给出了与 replace(seq_along(x), is.na(x), NA) 相同的结果,可以在它的位置使用。
    • 如果x 是所有 NA 值并且c(arg1, arg2)[1] 给出与if (length(arg1) == 0) arg2 else arg1 相同的结果,which.max 将返回零长度结果,可以在其位置使用。

    没有使用任何包。

    max_pos <- function(x) c(which.max(seq_along(x) + 0*x), length(x))[1]
    is_max <- function(x) seq_along(x) == max_pos(x)
    subset(data, !!ave(value, city, FUN = is_max))
    

    给予:

      year      city value
    1 2010    Berlin  1234
    4 2013    Munich  6372
    5 2013 Frankfurt    NA
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-05
      • 2016-06-09
      • 2020-09-08
      相关资源
      最近更新 更多