r-调整函数,使其不在所有行中循环,而是仅在组中的所有行中进行循环

  • 本文关键字:循环 调整 函数 r function for-loop dplyr
  • 更新时间 :
  • 英文 :


考虑下面的玩具数据集和函数:基本上,它在数据集df的行中循环,并根据一些标准查找匹配项。如果存在匹配,则观察结果将与其中一个匹配的行号相匹配。

dataset <- data.frame(id_dom = c(20, 20, 20, 250, 250, 250, 
254, 254, 254),        
p201 = c(1, NA, 2, NA, NA, NA, 2, 1, 2), 
V2009 = c(63, 42, 64, 26, 5, 4, 69, 30, 68)
)
match1 <- function(i, df) {
j <- 1:nrow(df)

if(!is.na(df$p201[i])){
l <- df$p201[i]
} else{

k <-  abs(df$V2009[i] - df$V2009[j]) <= 1
l <- ifelse(any(k), which(k), i)
}

return(l)
}

这就是我应用函数的方式:

dataset2 <- dataset %>%
group_by(id_dom,
index = map_dbl(seq(nrow(.)), 
~ .x %>% match1(df = dataset))) %>%
mutate(p201 = (first(na.omit(V2009)) - 1)*100)

正如你所看到的,我的最终目标是通过indexid_dom对观测结果进行配对——因此,如果i只运行每个id_dom组的行,而不是整个数据集,那么速度会更快(我认为它也会产生更好的结果(。

我想要一个答案:

i( 不将id_dom的分组放在match1函数中,而是放在管道中。ii(这使我可以编写类似map_dbl(seq(nrow(.)), ~ .x %>% match1(df = . ))的东西,这样,如果我之前创建了V2009变量,那么在运行函数之前就不需要破坏链。

谢谢!

您只能传递函数中所需的变量,而不能传递数据帧。这里是一个简化的函数CCD_ 10。

match2 <- function(x, y, val) {
if(is.na(x))
return(which.max(abs(y - val) <= 1))
else return(x)
} 

这可以用作:

library(dplyr)
library(purrr)
dataset3 <- dataset %>%
group_by(id_dom, index = map2_dbl(p201, V2009, match2, V2009)) %>%
mutate(p201 = (first(na.omit(V2009)) - 1)*100)
dataset3
# A tibble: 9 x 4
# Groups:   id_dom, index [6]
#  id_dom  p201 V2009 index
#   <dbl> <dbl> <dbl> <dbl>
#1     20  6200    63     1
#2     20  4100    42     2
#3     20  4100    64     2
#4    250  2500    26     4
#5    250   400     5     5
#6    250   400     4     5
#7    254  6800    69     2
#8    254  2900    30     1
#9    254  6800    68     2

这给出了与dataset2类似的结果,可以验证:

identical(dataset2, dataset3)
#[1] TRUE

通过'id_dom'分组后,我们可以在match中使用cur_data而不是dataset

library(dplyr)
library(purrr)
dataset %>%
# // grouped by id_dom
group_by(id_dom) %>%
# // create new group by looping over the sequence of rows
# // apply the match1
group_by(index = map_dbl(seq(n()), ~ 
match1(.x, df = cur_data())), .add = TRUE) %>%
# // update the p201
mutate(p201 = (first(na.omit(V2009)) - 1)*100)

或使用group_split

dataset %>% 
group_split(id_dom) %>%
map_dfr(., ~ .x %>%
group_by(index = map_dbl(row_number(),
~ match1(.x, df = cur_data()))) %>%
mutate(p201 = (first(na.omit(V2009)) - 1)*100))

最新更新