r语言 - 将 NA 替换为组中的下一个可用号码



我有一个相对较大的数据集,我想将特定年份的价格和特定 ID 号的 NA 值替换为明年组中相同ID 号的可用值。下面是一个可重现的示例:

ID <- c(1,2,3,2,2,3,1,4,5,5,1,2,2)
year <- c(2000,2001,2002,2002,2003,2007,2001,2000,2005,2006,2002,2004,2005)
value <- c(1000,20000,30000,NA,40000,NA,6000,4000,NA,20000,7000,50000,60000)
data <- data.frame(ID, year, value)
ID year value
1   1 2000  1000
2   2 2001 20000
3   3 2002 30000
4   2 2002    NA
5   2 2003 40000
6   3 2007    NA
7   1 2001  6000
8   4 2000  4000
9   5 2005    NA
10  5 2006 20000
11  1 2002  7000
12  2 2004 50000
13  2 2005 60000

因此,例如,对于 ID=2,我们有以下值和年份:

ID year value
2 2001  20000
2 2002  NA
2 2003  40000
2 2004  50000
2 2005  60000

所以在上面的情况下,NA应该被40000(明年的值)替换。其他 ID 也是如此。 最终结果应采用以下形式:

ID year value
1 2000  1000
1 2001  6000
1 2002  7000
2 2001  20000
2 2002  40000
2 2003  40000
2 2004  50000
2 2005  60000
3 2007    NA
4 2000  4000
5 2005  20000
5 2006  20000

请注意,对于 ID=3,由于没有明年可用,我们希望保持原样。这就是为什么它以 NA 的形式出现

如果您能提出解决方案,我将不胜感激
谢谢

dplyr解决方案

library(tidyverse)
data2 <- data %>%
dplyr::group_by(ID) %>%
dplyr::arrange(year) %>% 
dplyr::mutate(replaced_value = ifelse(is.na(value), lead(value), value))
print(data2)
# A tibble: 13 x 4
# Groups:   ID [5]
ID  year value replaced_value
<dbl> <dbl> <dbl>          <dbl>
1     1  2000  1000           1000
2     4  2000  4000           4000
3     2  2001 20000          20000
4     1  2001  6000           6000
5     3  2002 30000          30000
6     2  2002    NA          40000
7     1  2002  7000           7000
8     2  2003 40000          40000
9     2  2004 50000          50000
10     5  2005    NA          20000
11     2  2005 60000          60000
12     5  2006 20000          20000
13     3  2007    NA             NA

尝试以下tidyverse方法,使用标志检查连续年份和fill()以完成数据:

library(tidyverse)
#Data
ID <- c(1,2,3,2,2,3,1,4,5,5,1,2,2)
year <- c(2000,2001,2002,2002,2003,2007,2001,2000,2005,2006,2002,2004,2005)
value <- c(1000,20000,30000,NA,40000,NA,6000,4000,NA,20000,7000,50000,60000)
data <- data.frame(ID, year, value)
#Code
data2 <- data %>% arrange(ID,year) %>%
group_by(ID) %>% 
mutate(Flag=c(1,diff(year))) %>%
fill(value,.direction = 'downup') %>%
mutate(value=ifelse(Flag!=1,NA,value)) %>% select(-Flag)

输出:

# A tibble: 13 x 3
# Groups:   ID [5]
ID  year value
<dbl> <dbl> <dbl>
1     1  2000  1000
2     1  2001  6000
3     1  2002  7000
4     2  2001 20000
5     2  2002 20000
6     2  2003 40000
7     2  2004 50000
8     2  2005 60000
9     3  2002 30000
10     3  2007    NA
11     4  2000  4000
12     5  2005 20000
13     5  2006 20000

你可以做:

library(dplyr)
data %>%
group_by(ID) %>%
mutate(value = coalesce(value, as.integer(sapply(pmin(year + 1, max(year)), function(x) value[year == x])))) %>%
arrange(ID, year)

输出:

# A tibble: 13 x 3
# Groups:   ID [5]
ID  year value
<dbl> <dbl> <dbl>
1     1  2000  1000
2     1  2001  6000
3     1  2002  7000
4     2  2001 20000
5     2  2002 40000
6     2  2003 40000
7     2  2004 50000
8     2  2005 60000
9     3  2002 30000
10     3  2007    NA
11     4  2000  4000
12     5  2005 20000
13     5  2006 20000

现在,如果您想将NA替换为紧随其后的任何值 - 即即使year不一定是连续的 - 您可以执行以下操作:

library(tidyverse)
data %>%
arrange(ID, year) %>%
group_by(ID, idx = cumsum(is.na(value))) %>%
fill(value, .direction = 'up') %>%
ungroup %>%
select(-idx)

这在data.table中要简单得多(并且可能更快):

library(data.table)
setDT(data)[order(ID, year), ][
, value := nafill(value, type = 'nocb'), by = .(ID, cumsum(is.na(value)))]

最新更新