【问题标题】:filling in missing value from lagged value in R从R中的滞后值填充缺失值
【发布时间】:2019-10-18 01:19:47
【问题描述】:

我有一个这样的数据框:

ID     year  mstat change lint
8049    1995    1   NA    NA
8049    1996    1   0     1994
8049    1997    1   NA    NA
8049    1998    1   0     1996
8049    1999    1   NA    NA
8049    2000    1   0     1998
8049    2001    1   NA      NA
8049    2002    1   0     2000
8049    2003    NA  NA    NA
8049    2004    NA  NA    NA
8049    2005    NA  NA    NA
8049    2006    NA  NA    NA
8049    2007    NA  NA    NA
8049    2008    1   0     2002
8049    2009    NA  NA    NA
8049    2010    1   0     2008
8049    2011    NA  NA    NA
8049    2012    2   1     2008
8049    2013    NA  NA    NA
  1. mstat=婚姻状况,

  2. lint=上次采访日期

  3. change=婚姻状况改变

对于特定个人,year=2008 中的最后一次采访日期是2002。而year=2008中婚姻状况的变化是0。这意味着从 2003 年到 2007 年的婚姻状况应该与 2002 年或 2008 年的婚姻状况相同。如何使用 2002/2008 mstat 填写 2003 到 2007 年的 mstat 个人以及整个R中的数据集? (对于不同的个体,缺失值在不同的年份。)

我想要的输出是(在 mstat_updated 列中,从 2003 年到 2007 年,是 1。)

 ID   year mstat change lint mstat_updated
8049   2000 1   0       1998    1
8049   2001 1   NA      NA      1
8049   2002 1   0       2000    1
8049   2003 NA  NA      2002    1
8049   2004 NA  NA     2002     1
8049   2005 NA  NA      2002    1
8049   2006 NA  NA      2002    1
8049   2007 NA  NA      2002    1
8049   2008 1   0       2002    1
8049   2009 NA  NA      2008    1
8049   2010 1   0       2008    1
8049   2011 NA  NA      2010    NA
8049   2012 2   1       2010    2

按照 Ben 的建议尝试代码后,我得到下表,其中所有 change 值都是 TRUE。

df %>%
  fill(lint, .direction = 'up') %>%
  group_by(lint) %>%
  mutate(anychange = any(change > 0),
         mstat_updated = ifelse(anychange, mstat, last(mstat)))




ID    year  mstat change lint anychange mstat_updated
8049    1992    1   1   1991    TRUE    1
8049    1993    1   0   1992    TRUE    1
8049    1994    1   0   1993    TRUE    1
8049    1995    NA  NA  1994    TRUE    NA
8049    1996    1   0   1994    TRUE    1
8049    1997    NA  NA  1996    TRUE    NA
8049    1998    1   0   1996    TRUE    1
8049    1999    NA  NA  1998    TRUE    NA
8049    2000    1   0   1998    TRUE    1
8049    2001    NA  NA  2000    TRUE    NA
8049    2002    1   0   2000    TRUE    1
8049    2003    NA  NA  2002    TRUE    NA
8049    2004    NA  NA  2002    TRUE    NA
8049    2005    NA  NA  2002    TRUE    NA
8049    2006    NA  NA  2002    TRUE    NA
8049    2007    NA  NA  2002    TRUE    NA
8049    2008    1   0   2002    TRUE    1
8049    2009    NA  NA  2008    TRUE    NA
8049    2010    1   0   2008    TRUE    1
8049    2011    NA  NA  2008    TRUE    NA
8049    2012    2   1   2008    TRUE    2
8049    2013    NA  NA  2012    TRUE    NA
8049    2014    3   1   2012    TRUE    3
8049    2015    NA  NA  2014    TRUE    NA
8049    2016    3   0   2014    TRUE    3


 head(df,20L)
       ID    year  mstat change  lint anychange mstat_updated
   <fct>    <fct>  <int>  <int>  <dbl> <lgl>     <int>
 1 8049  1993      1      0  1992        TRUE      1
 2 8049  1994      1      0  1993        TRUE      1
 3 8049  1995     NA     NA  1994        TRUE      NA
 4 8049  1996      1      0  1994        TRUE      1
 5 8049  1997     NA     NA  1996        TRUE     NA
 6 8049  1998      1      0  1996        TRUE      1
 7 8049  1999     NA     NA  1998        TRUE     NA
 8 8049  2000      1      0  1998        TRUE      1
 9 8049  2001     NA     NA  2000        TRUE      NA
10 8049  2002      1      0  2000        TRUE      1
11 8049  2003     NA     NA  2002        TRUE      NA
12 8049  2004     NA     NA  2002        TRUE      NA
13 8049  2005     NA     NA  2002        TRUE      NA
14 8049  2006     NA     NA  2002        TRUE      NA
15 8049  2007     NA     NA  2002        TRUE      NA
16 8049  2008      1      0  2002        TRUE       1
17 8049  2009     NA     NA  2008        TRUE       NA
18 8049  2010      1      0  2008        TRUE       1
19 8049  2011     NA     NA  2008        TRUE       NA
20 8049  2012      2      1  2008        TRUE       2


dput() gives the following structure

  structure(list(ID = structure(c(4143L, 4143L, 4143L, 4143L, 4143L, 
   4143L, 4143L, 4143L, 4143L, 4143L), .Label = c("1", "2", "3", 
  .............
structure(15:24, .Label = c("1979", 
"1980", "1981", "1982", "1983", "1984", "1985", "1986", "1987", 
"1988", "1989", "1990", "1991", "1992", "1993", "1994", "1995", 
"1996", "1997", "1998", "1999", "2000", "2001", "2002", "2003", 
"2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", 
"2012", "2013", "2014", "2015", "2016"), class = "factor"), mstat = c(1L, 
1L, NA, 1L, NA, 1L, NA, 1L, NA, 1L), change = c(0L, 0L, NA, 0L, 
 NA, 0L, NA, 0L, NA, 0L), lint = c(1992, 1993, 1994, 1994, 1996, 
 1996, 1998, 1998, 2000, 2000), anychange = c(TRUE, TRUE, TRUE, 
 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE), mstat_updated = c(1L, 
 1L, NA, 1L, NA, 1L, NA, 1L, NA, 1L)), class = c("tbl_df", "tbl", 
 "data.frame"), row.names = c(NA, -10L))

所以,在听从 Ben 绝对有用的建议之后,我终于得到了我想要的。

首先,我逐年修复了 lint(它可能效率不高,但无论如何都能正常工作),其中 lint 在数据中不正确(例如,正如 Ben 指出的 2012 年数据 - 最后一次采访 lint 是 2008 年,但是是 2010 年更新的数据)。我的示例代码是:

df$lint_up<-ifelse(df$year==2012 & df$lint==2008 & lag(df$lint,2)==2008, 2010, df$lint)

 df$lint_up<-ifelse(df$year==2004  & df$lint==2000 & lag(df$lint,2)==2000, 2002, df$lint)

 df$lint_up<-ifelse(df$year==2000  & df$lint==1996 & lag(df$lint,2)==1996, 1998, df$lint)

然后我填写 lint_updated (lint_up) 变量:

mk<-df%>%
  group_by(ID)%>%
  fill(lint_up,.direction = 'up')

现在,对于mstat_updated,我主要遵循 Ben 的建议,但我将 ID 和 lint_up 都分组:

abc<-mk %>%
  group_by(lint_up, ID) %>%
  mutate(mstat_updated = ifelse(is.na(mstat) & any(last(change==0)), 
  last(mstat), mstat))

【问题讨论】:

  • 你能澄清一下最终的输出应该是什么吗? (请编辑您的问题。)
  • 我已经添加了我想要的输出。谢谢你的要求。

标签: r repeat


【解决方案1】:

于 2019 年 10 月 19 日编辑:

感谢您添加更多信息。我希望这更接近。

一种tidyverse 方法是使用NA 值填写上次采访lint 年。使用.direction = 'up',您将根据最近一年的数据填写。

然后,group_by 上一个面试年 (lint) 将仅根据这些年份进行更改。这将允许您根据 2008 mstat 更改 2003-2007 年。

我发现的另一个问题是 2012 年的数据 - 最后一次采访 lint 是 2008 年,但似乎有 2010 年的数据更新。

使用最近的编辑,现在将执行以下操作:

  • 过滤有数据的记录
  • 创建一个新变量last_year_data - 类似于lint,但会捕获有数据的2010年,但lint错过了
  • 这会将 change 变量中的 NA 更改为 0 - 这将捕获 any(change) 以确定不应更新 mstat_updated 的位置

我认为这将解决一些问题 - 但可能会带来其他问题。如果这不起作用,我不介意删除我的答案(以防其他人更有可能回应) - 或者您可以尝试发布一个新的/修订的问题。

library(dplyr)

df %>%
  filter(!is.na(mstat) & (mstat >= 0)) %>%
  mutate(last_year_data = lag(year)) %>%
  right_join(df) %>% 
  fill(last_year_data, .direction = 'up') %>%
  group_by(last_year_data) %>%
  mutate(mstat_updated = last(mstat),
         change = replace_na(change, 0)) %>%
  mutate(mstat_updated = ifelse(any(change > 0) & is.na(mstat), mstat, mstat_updated))

# A tibble: 34 x 7
# Groups:   last_year_data [20]
      ID  year mstat change  lint last_year_data mstat_updated
   <int> <int> <int>  <dbl> <int>          <int>         <int>
 1  8049  1983     0      0  1982           1983             0
 2  8049  1984     0      0  1983           1983             0
 3  8049  1985     0      0  1984           1984             0
 4  8049  1986     0      0  1985           1985             0
 5  8049  1987     0      0  1986           1986             0
 6  8049  1988     0      0  1987           1987             0
 7  8049  1989     0      0  1988           1988             0
 8  8049  1990     0      0  1989           1989             0
 9  8049  1991     0      0  1990           1990             0
10  8049  1992     1      1  1991           1991             1
11  8049  1993     1      0  1992           1992             1
12  8049  1994     1      0  1993           1993             1
13  8049  1995    NA      0  1994           1994             1
14  8049  1996     1      0  1994           1994             1
15  8049  1997    NA      0  1996           1996             1
16  8049  1998     1      0  1996           1996             1
17  8049  1999    NA      0  1998           1998             1
18  8049  2000     1      0  1998           1998             1
19  8049  2001    NA      0  2000           2000             1
20  8049  2002     1      0  2000           2000             1
21  8049  2003    NA      0  2002           2002             1
22  8049  2004    -5      0  2002           2002             1
23  8049  2005    NA      0  2002           2002             1
24  8049  2006    -5      0  2002           2002             1
25  8049  2007    NA      0  2002           2002             1
26  8049  2008     1      0  2002           2002             1
27  8049  2009    NA      0  2008           2008             1
28  8049  2010     1      0  2008           2008             1
29  8049  2011    NA      0  2008           2010            NA
30  8049  2012     2      1  2008           2010             2
31  8049  2013    NA      0  2012           2012            NA
32  8049  2014     3      1  2012           2012             3
33  8049  2015    NA      0  2014           2014             3
34  8049  2016     3      0  2014           2014             3

【讨论】:

  • 非常感谢。我认为它会起作用,但应该对lint.. 进行一些修改。我已经编辑了我想要的输出。所以,2002年有一次面试,之前最后一次面试是在2000年。但是,2003-2007年没有面试。所以,在2003-2007年,lint应该是2002年。这会很有帮助如果你能告诉我如何用 2002 而不是 2000 填写 2003-2007 的 lint。谢谢。
  • 我可能想通了。那不应该是填充(lint,.direction ='up')吗?但是,我所有的 anychange = any(change > 0) 都变成了TRUE。请让我知道如何解决它。谢谢。
  • 非常感谢您的回复。正如我所说,我的 anychange 专栏只有 TRUE 。事实上,对于整个数据集,它只有TRUE。这就是为什么我没有得到正确的 mstat_updated。我正在发布我对这个特定观察的最终结果。请让我知道是否有任何其他方法可用于任何(更改> 0),以便我的任何更改变量值变得正确。再次感谢。
  • 非常感谢您的帮助。至于NA 所关注的mstat 和change 2003、2005 和2007。我后来在运行代码之前用NA 替换了缺失值。我已经编辑了初始数据。我还发布了一些 head() 和 dput()..我删除了 dput() 中的大部分标签。如果您需要更多信息,请与我们联系。非常感谢!
  • 嘿,Ben,我终于得到了我想要的东西。我已经在我的帖子中添加了我的代码。我非常感谢你为我指明了正确的方向。两天来,我一直在尝试使用for/while 循环,但运气不佳。最后,您的建议使一切变得不同。非常感谢您的宝贵时间和帮助!
猜你喜欢
  • 2019-01-29
  • 2012-10-25
  • 2020-04-13
  • 2023-04-01
  • 1970-01-01
  • 2017-08-15
  • 2016-08-26
相关资源
最近更新 更多