在 R 中管道的中间放置一个 for 环



我需要一些帮助来使我的代码更精简一些。

这是我原始数据集的一小部分:

library(tidyverse)
dataset <- data.frame(UPA = c(130033353, 130033353, 130033353, 130033353,
130033353, 230036930, 230036930, 230036930, 230036930, 230036930,
230124582, 230124582, 230124582, 230124582, 230124582, 240039107,
240039107, 240039107, 240039107, 240039107, 320022393, 320022393,
320022393, 320022393, 320022393, 330093898, 330093898, 330093898,
330093898, 330093898),
UF = c(13, 13, 13, 13, 13, 23, 23, 23,23, 23, 23, 23, 23, 23, 23, 24, 24,
24, 24, 24, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33),
V1008 = c(1, 1, 1, 1, 1, 5, 5, 5, 5,5, 11, 11, 11, 11, 11,
8, 8, 8, 8, 8, 3, 3, 3, 3, 3, 9, 9, 9,9, 9),
V1014 = c(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
V2008 = c(22, 23, 12, 28, 29, 13, 9, 9, 2, 22, 18, 5, 8,
16, 16, 12, 24, 2, 25, 28, 7, 7, 7, 15, 15, 6,
6, 18, 14, 14),
V20081 = c(1, 9, 6, 3, 5, 9, 7, 6, 9, 5, 2, 6, 1, 5, 9,
10, 5, 4, 5, 1, 7, 7, 7, 5, 5, 8, 8, 4, 8, 8),
V20082 = c(1952, 1964, 1995, 1999, 2009, 1993, 1998, 2000,
2003, 2011, 1967, 1990, 1993, 1996, 2001, 1947, 1996,
1998, 1997, 2012, 2010, 2010, 2010, 2011, 2011, 1981, 1981, 1984,
2006, 2006),
V2003 = c(1, 2, 6, 8, 10, 2, 9, 10, 12, 15, 2, 3,
5, 7, 11, 2, 6, 7, 7, 9, 3, 3, 3, 4, 4, 1, 1, 2, 4, 4),
V2007 = c(1, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 2, 1, 2,
2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2),
n_p = c(1, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA,
NA, 1, 2, 1, NA, NA),
id_dom = c(2499L, 2499L, 2499L, 2499L,
2499L, 10962L, 10962L, 10962L, 10962L, 
10962L, 12618L, 12618L, 12618L, 12618L, 12618L, 13673L, 
13673L, 13673L, 13673L, 13673L, 25945L, 25945L, 25945L, 
25945L, 25945L, 28145L, 28145L, 28145L, 28145L, 28145L))

我想根据n_p的值以迭代方式更新p201变量的值。n_p可以从 1 到 5(虽然不是dataset,我很抱歉无法提取包含所有可能情况的样本(。在第一波中,如果n_p == 1,我将p201分配给等于100*(n_p-1) + V2003,否则NA。之后,我从 2 到 5 做同样的事情,只考虑仍然缺少p201的行。

这是代码:

final_df <- dataset %>%
group_by(UF, UPA, V1008, V1014, V2007, 
V2008, V20081, V20082, V2003) %>%
mutate(p201 = ifelse(n_p == 1 & V2008 != 99 &
V20081 != 99 & V20082 != 9999,
100*(n_p-1) + V2003, NA)) %>%
fill(p201, .direction = 'down') %>%
mutate(p201 = ifelse(n_p == 1,
p201,
ifelse(n_p == 2 & is.na(p201) & V2008 != 99 &
V20081 != 99 & V20082 != 9999, 
100*(n_p-1) + V2003,
NA))) %>%
fill(p201, .direction = 'down') %>%
mutate(p201 = ifelse(n_p %in% 1:2,
p201,
ifelse(n_p == 3 & is.na(p201) & V2008 != 99 &
V20081 != 99 & V20082 != 9999,
100*(n_p-1) + V2003,
NA))) %>%
fill(p201, .direction = 'down') %>%
mutate(p201 = ifelse(n_p %in% 1:3,
p201,
ifelse(n_p == 4 & is.na(p201) & V2008 != 99 &
V20081 != 99 & V20082 != 9999,
100*(n_p-1) + V2003,
NA))) %>%
fill(p201, .direction = 'down') %>%
mutate(p201 = ifelse(n_p %in% 1:4,
p201,
ifelse(n_p == 5 & is.na(p201) & V2008 != 99 &
V20081 != 99 & V20082 != 9999,
100*(n_p-1) + V2003,
NA))) %>%
ungroup() %>%
mutate_at(c('UF', 'UPA', 'V1008', 'p201'), as.character) %>%
mutate(idind = ifelse(is.na(p201),
NA,
paste0(V1014, UF, UPA, V1008, p201)))

我显然可以使用类似for循环的东西(或者更好的东西,使用map?(使代码更精简一些,但我不知道如何使用 tidyverse 的语法在管道流中插入循环。

有人可以帮忙吗?我想要的输出正是导致final_df的输出,但代码更干净。

PS:请不要介意结果会在p201中生成大量 NA - 整个数据集更复杂,这可能并非如此。

编辑我已经通过调整 Limy 的答案找到了解决方案——我不知道递归函数。

事情是这样的:

loop <- function(data,
interview = 2,
int_final = 5){
data <- data %>%
group_by(UF, UPA, V1008, V1014, V2007,
V2008, V20081, V20082, V2003) %>%
fill(p201, .direction = 'down') %>%
mutate(p201 = ifelse(
n_p %in% 1:(interview-1),
p201,
ifelse(
n_p == interview  & is.na(p201) &
V2008 != 99 &
V20081 != 99 & V20082 != 9999,
100 * (n_p - 1) + V2003,
NA
)
))
if(interview == int_final){
return(data)
} else{
return(loop(data, interview + 1, int_final))
}
}
final_dataset <- dataset %>%
group_by(UF, UPA, V1008, V1014, V2007,
V2008, V20081, V20082, V2003) %>%
mutate(p201 = ifelse(n_p == 1  & V2008 != 99 &
V20081 != 99 & V20082 != 9999,
100*(n_p-1) + V2003, NA)) %>%
loop() %>%
ungroup() %>%
mutate_at(c('UF', 'UPA', 'V1008', 'p201'), as.character) %>%
mutate(idind = ifelse(is.na(p201),
NA,
paste0(V1014, UF, UPA, V1008, p201)))

嗯。 听起来像是递归编程可能会解决问题。 我不知道你为什么要这样做,你没有提供想要的结果,所以我无法检查我的结果,但这样的事情可能会起作用。

[未经测试的代码]

doIt <- function(data, currentDepth=1, maxDepth=5) {
data <- data %>%
group_by(UF, UPA, V1008, V1014, V2007, 
V2008, V20081, V20082, V2003) %>%
mutate(p201 = ifelse(n_p %in% 1:currentDepth & V2008 != 99 & V20081 != 99 & V20082 != 9999,
100*(n_p-1) + V2003, 
NA)) %>%
fill(p201, .direction = 'down')
if (currentDepth == maxDepth) return(data)
else return (doIt(data, currentDepth+1, maxDepth))
}
final_dataset <- doIt(dataset)

我试图概括你的ifelse. 该函数要么再次调用自身(如果当前深度<maxDepth(,要么返回自己的结果。>

最新更新