用最近可用的数据替换列(用purrr替换嵌套的forloop)

用最近可用的数据替换列(用purrr替换嵌套的forloop),r,foreach,purrr,mutate,R,Foreach,Purrr,Mutate,将嵌套的STATA forloops转换为R tidyverse/purrr语法 我试图用foreach或purr来做这件事,但我一直被卡住 STATA代码: 以下是数据示例: 目标: 我试图为每个变量(zip_agg、child_agg、income_agg)创建一个当前“agg”变量,方法是在不同日期的变量之间运行for循环,以替换最新数据中的值 如果缺少最新版本,则应返回到下一个最新日期。我已经开始编码,但我知道这是不正确的 variable_date<-c("20190601",

将嵌套的STATA forloops转换为R tidyverse/purrr语法

我试图用foreach或purr来做这件事,但我一直被卡住

STATA代码:

以下是数据示例:

目标:

我试图为每个变量(zip_agg、child_agg、income_agg)创建一个当前“agg”变量,方法是在不同日期的变量之间运行for循环,以替换最新数据中的值

如果缺少最新版本,则应返回到下一个最新日期。我已经开始编码,但我知道这是不正确的

variable_date<-c("20190601", "20180401", "20171001", "20160801")
variable_list<-c("zip", "income", "child")


# using foreach package
foreach(x=variable_list, .combine = 'cbind') %:%
  foreach(y=variable_date, .combine = 'c') %do%
  { 

    var_agg<-str_c(x, "_agg") #create variable name

my.df%<>%
      mutate(var_agg=NA,
      var_agg=ifelse(is.na({{var_agg}})==T, my.df[str_c(x,y)], {{var_agg}}))

variable\u date也许,一个选项是重新格式化为“long”格式,然后根据上一个日期进行
筛选
切片

library(dplyr)
library(tidyr)
library(stringr)
df1 %>%
    mutate(rn = row_number()) %>%
    pivot_longer(cols = -rn, names_to = c(".value", "date"), names_sep="_") %>%
    group_by(rn) %>%
    slice(which.max(date)) %>%
    ungroup %>%
    select(-rn) %>%
    rename_all( ~ str_c(., '_agg')) %>%
    bind_cols(df1, .)

如果我们不需要
NA
,即如果最后一个元素是基于日期的
NA
,那么一个选项是
之后总结
,按“日期”排列

df1 %>% 
    mutate(rn = row_number()) %>%
    pivot_longer(cols = -rn, names_to = c(".value", "date"), names_sep="_") %>% 
    arrange(rn, date) %>% 
    group_by(rn) %>% 
    summarise_at(vars(zip:child), ~ last(.[!is.na(.)])) %>%
    ungroup %>%
    select(-rn) %>%
    rename_all( ~ str_c(., '_agg')) %>%
    bind_cols(df1, .)
#zip_20190601 zip_20180401 zip_20171001 zip_20160801 income_20190601 income_20180401 income_20171001 income_20160801 child_20160801
#1            NA        11440        12016        15686           75038           63573           82391           47517              0
#2         13089        12626        13670        16155           89494           64984           62603           47252              0
#3         13258        12249        13333        16819              NA              NA           48231           45729              0
#4            NA           NA        18480        18611           89480           67348           55516           45863              0
#5         13990        10497        12573        13406           70053           63850           87833           48332              1
#6         17005        11491        15227        17518           78087           70741           46318           47823              1
#7         17174        17006        13461        11189           76780           66649           54578           46196              1
#8         12452        15317        18049        14284           76654           73583           70090           48281              0
#9         18449        14262        11013        17810           91422           79722           53948           45986              0
#10        11429        11731        13564        14603           84282           60190           45133           46956              0
#   child_20171001 child_20180401 child_20190601 zip_agg income_agg child_agg
#1               1              1              2   11440      75038         2
#2               1              1              2   13089      89494         2
#3               1              1              2   13258      48231         2
#4               1              1              2   18480      89480         2
#5               2              2              3   13990      70053         3
#6               2              2              3   17005      78087         3
#7               2              2              3   17174      76780         3
#8               1              1              2   12452      76654         2
#9               1              1              2   18449      91422         2
#10              1              1              2   11429      84282         2
更新 如果名称中没有分隔符,我们仍然可以使用regex lookaround在
names\u sep

df2 %>% 
    mutate(rn =row_number()) %>% 
    pivot_longer(cols = -rn, names_to = c(".value", "date"),
        names_sep="(?<=[a-z])(?=[0-9])") %>% 
    arrange(rn, date) %>% 
    group_by(rn) %>% 
    summarise_at(vars(zip:child), ~ last(.[!is.na(.)])) %>%
    ungroup %>%
    select(-rn) %>%
    rename_all( ~ str_c(., '_agg')) %>%
    bind_cols(df2, .)
#   zip20190601 zip20180401 zip20171001 zip20160801 income20190601 income20180401 income20171001 income20160801 child20160801 child20171001
#1           NA       11440       12016       15686          75038          63573          82391          47517             0             1
#2        13089       12626       13670       16155          89494          64984          62603          47252             0             1
#3        13258       12249       13333       16819             NA             NA          48231          45729             0             1
#4           NA          NA       18480       18611          89480          67348          55516          45863             0             1
#5        13990       10497       12573       13406          70053          63850          87833          48332             1             2
#6        17005       11491       15227       17518          78087          70741          46318          47823             1             2
#7        17174       17006       13461       11189          76780          66649          54578          46196             1             2
#8        12452       15317       18049       14284          76654          73583          70090          48281             0             1
#9        18449       14262       11013       17810          91422          79722          53948          45986             0             1
#10       11429       11731       13564       14603          84282          60190          45133          46956             0             1
#   child20180401 child20190601 zip_agg income_agg child_agg
#1              1             2   11440      75038         2
#2              1             2   13089      89494         2
#3              1             2   13258      48231         2
#4              1             2   18480      89480         2
#5              2             3   13990      70053         3
#6              2             3   17005      78087         3
#7              2             3   17174      76780         3
#8              1             2   12452      76654         2
#9              1             2   18449      91422         2
#10             1             2   11429      84282         2
df2%>%
变异(rn=行数())%>%
pivot_longer(cols=-rn,names_to=c(“.value”,“date”),

names_sep=“(?也许,一个选项是将形状改为“长”格式,然后根据上一个日期执行
筛选
切片

library(dplyr)
library(tidyr)
library(stringr)
df1 %>%
    mutate(rn = row_number()) %>%
    pivot_longer(cols = -rn, names_to = c(".value", "date"), names_sep="_") %>%
    group_by(rn) %>%
    slice(which.max(date)) %>%
    ungroup %>%
    select(-rn) %>%
    rename_all( ~ str_c(., '_agg')) %>%
    bind_cols(df1, .)

如果我们不需要
NA
,即如果最后一个元素是基于日期的
NA
,那么一个选项是
之后总结
,按“日期”排列

df1 %>% 
    mutate(rn = row_number()) %>%
    pivot_longer(cols = -rn, names_to = c(".value", "date"), names_sep="_") %>% 
    arrange(rn, date) %>% 
    group_by(rn) %>% 
    summarise_at(vars(zip:child), ~ last(.[!is.na(.)])) %>%
    ungroup %>%
    select(-rn) %>%
    rename_all( ~ str_c(., '_agg')) %>%
    bind_cols(df1, .)
#zip_20190601 zip_20180401 zip_20171001 zip_20160801 income_20190601 income_20180401 income_20171001 income_20160801 child_20160801
#1            NA        11440        12016        15686           75038           63573           82391           47517              0
#2         13089        12626        13670        16155           89494           64984           62603           47252              0
#3         13258        12249        13333        16819              NA              NA           48231           45729              0
#4            NA           NA        18480        18611           89480           67348           55516           45863              0
#5         13990        10497        12573        13406           70053           63850           87833           48332              1
#6         17005        11491        15227        17518           78087           70741           46318           47823              1
#7         17174        17006        13461        11189           76780           66649           54578           46196              1
#8         12452        15317        18049        14284           76654           73583           70090           48281              0
#9         18449        14262        11013        17810           91422           79722           53948           45986              0
#10        11429        11731        13564        14603           84282           60190           45133           46956              0
#   child_20171001 child_20180401 child_20190601 zip_agg income_agg child_agg
#1               1              1              2   11440      75038         2
#2               1              1              2   13089      89494         2
#3               1              1              2   13258      48231         2
#4               1              1              2   18480      89480         2
#5               2              2              3   13990      70053         3
#6               2              2              3   17005      78087         3
#7               2              2              3   17174      76780         3
#8               1              1              2   12452      76654         2
#9               1              1              2   18449      91422         2
#10              1              1              2   11429      84282         2
更新 如果名称中没有分隔符,我们仍然可以使用regex lookaround在
names\u sep

df2 %>% 
    mutate(rn =row_number()) %>% 
    pivot_longer(cols = -rn, names_to = c(".value", "date"),
        names_sep="(?<=[a-z])(?=[0-9])") %>% 
    arrange(rn, date) %>% 
    group_by(rn) %>% 
    summarise_at(vars(zip:child), ~ last(.[!is.na(.)])) %>%
    ungroup %>%
    select(-rn) %>%
    rename_all( ~ str_c(., '_agg')) %>%
    bind_cols(df2, .)
#   zip20190601 zip20180401 zip20171001 zip20160801 income20190601 income20180401 income20171001 income20160801 child20160801 child20171001
#1           NA       11440       12016       15686          75038          63573          82391          47517             0             1
#2        13089       12626       13670       16155          89494          64984          62603          47252             0             1
#3        13258       12249       13333       16819             NA             NA          48231          45729             0             1
#4           NA          NA       18480       18611          89480          67348          55516          45863             0             1
#5        13990       10497       12573       13406          70053          63850          87833          48332             1             2
#6        17005       11491       15227       17518          78087          70741          46318          47823             1             2
#7        17174       17006       13461       11189          76780          66649          54578          46196             1             2
#8        12452       15317       18049       14284          76654          73583          70090          48281             0             1
#9        18449       14262       11013       17810          91422          79722          53948          45986             0             1
#10       11429       11731       13564       14603          84282          60190          45133          46956             0             1
#   child20180401 child20190601 zip_agg income_agg child_agg
#1              1             2   11440      75038         2
#2              1             2   13089      89494         2
#3              1             2   13258      48231         2
#4              1             2   18480      89480         2
#5              2             3   13990      70053         3
#6              2             3   17005      78087         3
#7              2             3   17174      76780         3
#8              1             2   12452      76654         2
#9              1             2   18449      91422         2
#10             1             2   11429      84282         2
df2%>%
变异(rn=行数())%>%
pivot_longer(cols=-rn,names_to=c(“.value”,“date”),

names_sep=“(?我们可以在这里使用
max.col
。我们将操作分为两部分,第一部分我们要计算所有
“zip”
“income”
列的最新值,第二部分我们要计算
“child”
列的最大值

variable_list <- c("zip", "income")

#Part 1 
df[paste0(variable_list, '_agg')] <- lapply(variable_list, function(x) {
     cols <- grep(x, names(df))
     df[cols][cbind(1:nrow(df), max.col(!is.na(df[cols]), ties.method = "first"))]
})

#Part 2
cols <- grep('child', names(df))
df$child_agg <- df[cols][cbind(1:nrow(df), max.col(df[cols]))]

#Result
df[13:15]

#   zip_agg income_agg child_agg
#1    11440      75038         2
#2    13089      89494         2
#3    13258      48231         2
#4    18480      89480         2
#5    13990      70053         3
#6    17005      78087         3
#7    17174      76780         3
#8    12452      76654         2
#9    18449      91422         2
#10   11429      84282         2

variable\u list我们可以在这里使用
max.col
。我们将操作分为两部分,第一部分我们要计算所有
“zip”
“income”
列的最新值,第二部分我们要计算
“child”
列的最大值

variable_list <- c("zip", "income")

#Part 1 
df[paste0(variable_list, '_agg')] <- lapply(variable_list, function(x) {
     cols <- grep(x, names(df))
     df[cols][cbind(1:nrow(df), max.col(!is.na(df[cols]), ties.method = "first"))]
})

#Part 2
cols <- grep('child', names(df))
df$child_agg <- df[cols][cbind(1:nrow(df), max.col(df[cols]))]

#Result
df[13:15]

#   zip_agg income_agg child_agg
#1    11440      75038         2
#2    13089      89494         2
#3    13258      48231         2
#4    18480      89480         2
#5    13990      70053         3
#6    17005      78087         3
#7    17174      76780         3
#8    12452      76654         2
#9    18449      91422         2
#10   11429      84282         2

variable\u列表刚用预期输出更新!刚用预期输出更新!可以动态指定变量吗?@brin你的意思是
variable\u日期谢谢!我刚刚意识到我的数据没有“\u”在变量名和变量日期之间。如何在不指定分隔符的情况下将文件重塑为长文件?我已编辑了该问题以反映正确的列标题。@brin尝试使用
names\u sep=“(?是否可以动态指定变量?@brin您的意思是
variable\u dateThank You!我刚刚意识到我的数据没有”_“在变量名和变量日期之间。我如何在不指定分隔符的情况下将文件重塑为长文件?我已编辑了该问题以反映正确的列标题。@brin尝试使用
names_sep=“(?如果我有更多的变量,如Child或更多的字符变量怎么办?@brin非常类似于“zip”和“income”列我们也可以在那里使用
lappy
,这样就可以对许多列执行。如果我有更多的变量,如Child或更多的字符变量呢?@brin类似于“zip”和“income”列,我们也可以在那里使用
lappy
,这样就可以对许多列执行。