R - 保留非 NA 的最新数据,除非只有 NA 可用

R - Keep newest data that is not NA, unless only NA available

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

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 的最高年份。我该怎么做?

我们可以使用data.table。将'data.frame'转换为'data.table'(setDT(data)),按'city'分组,我们指定'i'为降序order中的'year' ]索引,ifany个非NA'value',我们根据第一个非NA'value'或[=的索引对'Data.table'进行子集18=] return Data.table.

的子集
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]

使用 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)

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

请注意,max_pos 是通过使用以下事实变得紧凑的:

  • seq_along(x) * 0*x 中,0*x 是零和 NA 的向量,因此将它添加到 seq_along(x) 的相应元素中。也就是说,它给出的结果与 replace(seq_along(x), is.na(x), NA) 相同,可以用它代替。
  • which.max returns 零长度结果,如果 x 是所有 NA 值并且 c(arg1, arg2)[1] 给出与 if (length(arg1) == 0) arg2 else arg1 相同的结果,可用于它的位置。

没有使用包。

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