我有一个数据框test_case
。我在列(income
)中缺少数据。
test_case <- data.frame(
person=c(1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3),
year=c(2010, 2011, 2012, 2010, 2011, 2012, 2010, 2011, 2013, 2014, 2014, 2014),
income=c(4, 10, 13, NA, NA, NA, 13, NA, NA, NA, NA, NA),
cutoff=c(0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0)
)
变量cutoff
指定我希望将收入中的值“结转”到后续行中的次数(使用包动物园中的na.locf()方法)。例如,在上面的数据框中,截止值为2表示收入应该结转两次。
我已经看过关于指定如何使用na.locf来向前移n次当n是常数时的示例。但在我的情况下,我在泛化时遇到了问题(R -- Carry last observation forward n times当n正在改变时。
这是我的原始数据框:
person year income cutoff
1 1 2010 4 0
2 1 2011 10 0
3 1 2012 13 2
4 2 2010 NA 0
5 2 2011 NA 0
6 2 2012 NA 0
7 3 2010 13 3
8 3 2011 NA 0
9 3 2013 NA 0
10 3 2014 NA 0
11 3 2014 NA 0
12 3 2014 NA 0
这是所需的输出:
person year income cutoff
1 1 2010 4 0
2 1 2011 10 0
3 1 2012 13 2
4 2 2010 13 0
5 2 2011 13 0
6 2 2012 NA 0
7 3 2010 13 3
8 3 2011 13 0
9 3 2013 13 0
10 3 2014 13 0
11 3 2014 NA 0
12 3 2014 NA 0
答案 0 :(得分:5)
此处尝试使用data.table
。分组方法是@jeremys的答案,虽然我在这里避免使用ifelse
或lapply
,而是将根据第一个income
值复制的第一个income
值与NA
个值复制.N - (cutoff[1L] + 1L)
次。我自第一次cutoff > 0L)
library(data.table)
setDT(test_case)[which.max(cutoff > 0L):.N, # Or `cutoff > 0L | is.na(income)`
income := c(rep(income[1L], cutoff[1L] + 1L), rep(NA, .N - (cutoff[1L] + 1L))),
by = cumsum(cutoff != 0L)]
test_case
# person year income cutoff
# 1: 1 2010 4 0
# 2: 1 2011 10 0
# 3: 1 2012 13 2
# 4: 2 2010 13 0
# 5: 2 2011 13 0
# 6: 2 2012 NA 0
# 7: 3 2010 13 3
# 8: 3 2011 13 0
# 9: 3 2013 13 0
# 10: 3 2014 13 0
# 11: 3 2014 NA 0
# 12: 3 2014 NA 0
答案 1 :(得分:3)
以下是使用dplyr
的答案。
它的工作原理是按不同截止值的累积和进行分组。
如果cutoff为0,它会生成一个FALSE列表,并且TRUE的截止数量是未列出的并切成组的大小。
然后使用ifelse,收入未经修改或成为第一笔收入(即截止收入)。
library(dplyr)
test_case %>% group_by(z = cumsum(cutoff != 0)) %>%
mutate(income = ifelse(unlist(lapply(cutoff, function(x) rep(as.logical(x), max(1,x + 1))))[1:n()], income[1], income))
Source: local data frame [12 x 5]
Groups: z [3]
z person year income cutoff
(int) (dbl) (dbl) (dbl) (dbl)
1 0 1 2010 4 0
2 0 1 2011 10 0
3 1 1 2012 13 2
4 1 2 2010 13 0
5 1 2 2011 13 0
6 1 2 2012 NA 0
7 2 3 2010 13 3
8 2 3 2011 13 0
9 2 3 2013 13 0
10 2 3 2014 13 0
11 2 3 2014 NA 0
12 2 3 2014 NA 0
答案 2 :(得分:2)
使用na.locf
的解决方案可以与@ jeremycg的解决方案类似的方式工作。我们只需要按cumsum(cutoff != 0)
和另一个变换row_number
我的解决方案并不像jeremycg那样优雅,但这就是我接触它的方式:
library(dplyr)
library(zoo)
test_case %>%
mutate(
rownum = row_number(),
cutoff2 = ifelse(cutoff == 0, NA, cutoff + rownum),
cutoff2 = na.locf(cutoff2, na.rm = FALSE),
cutoff2 = ifelse(rownum > cutoff2, NA, cutoff2)
) %>%
group_by(z = cumsum(cutoff != 0), cutoff2) %>%
mutate(income = na.locf(income, na.rm = FALSE))
# Source: local data frame [12 x 7]
# Groups: z, cutoff2 [5]
#
# person year income cutoff rownum cutoff2 z
# (dbl) (dbl) (dbl) (dbl) (int) (dbl) (int)
# 1 1 2010 4 0 1 NA 0
# 2 1 2011 10 0 2 NA 0
# 3 1 2012 13 2 3 5 1
# 4 2 2010 13 0 4 5 1
# 5 2 2011 13 0 5 5 1
# 6 2 2012 NA 0 6 NA 1
# 7 3 2010 13 3 7 10 2
# 8 3 2011 13 0 8 10 2
# 9 3 2013 13 0 9 10 2
# 10 3 2014 13 0 10 10 2
# 11 3 2014 NA 0 11 NA 2
# 12 3 2014 NA 0 12 NA 2