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