我在dplyr中使用分组数据进行高级操作时遇到了一些问题。我不确定如何指定是否要引用观察级别的值,以及何时可以专门引用整个向量。
示例数据框:
df <- as.data.frame(
rbind(
c(11990, 2011, 1, 1, 2010),
c(11990, 2015, 1, 0, NA),
c(11990, 2017, 2, 1, NA),
c(11990, 2018, 2, 1, 2016),
c(11990, 2019, 2, 1, 2019),
c(11990, 2020, 1, 0, NA),
c(22880, 2013, 1, 1, NA),
c(22880, 2014, 1, 0, 2011),
c(22880, 2015, 1, 1, NA),
c(22880, 2018, 2, 0, 2014),
c(22880, 2020, 2, 0, 1979)))
names(df) <- c("id", "year", "house_apt", "moved", "year_moved")
# > df
# id year house_apt moved year_moved
# 1 11990 2011 1 1 2010
# 2 11990 2015 1 0 NA
# 3 11990 2017 2 1 NA
# 4 11990 2018 2 1 2016
# 5 11990 2019 2 1 2019
# 6 11990 2020 1 0 NA
# 7 22880 2013 1 1 NA
# 8 22880 2014 1 0 2011
# 9 22880 2015 1 1 NA
# 10 22880 2018 2 0 2014
# 11 22880 2020 2 0 1979
如果我做简单的变异操作:
library(dplyr)
df %>% mutate(year+2)
df %>% group_by(id) %>% mutate(year+2)
很明显,这里的“年份”是指每个单独的行值。即使我(由于某种原因)通过分组来做这件事也是如此。但是,如果我要执行以下两个涉及向量操作的操作:
df %>% mutate(sum(year))
df %>% group_by(id) %>% mutate(sum(year))
dplyr将“year”理解为整个组的年度值的整个向量。
然而,现在我在一个操作方面遇到了很多麻烦,我是否希望mutate
使用行值或整个向量。在我的数据框架中,我想为移动但未记录移动日期的个人创建一个猜测的移动年份,直到稍后的调查实例。请注意,数据非常混乱,我们要忽略一些荒谬的移动日期。
因此,我想为一个人移动但没有记录move_year的每一行创建一个“guess”值。我希望操作能够查看每个个体的移动日期的整个向量,子集仅包括当前年份之前的那些,并选出与当前行最接近年份的那个。细粒度示例:如果我们查看第3行,那个人在那一年移动,但没有移动日期。因此,我们希望查看该人(2010, NA, NA, 2016, 2019, NA)
的整个year_moved向量,并选择与年份(2017
)的行#3值最接近且最好早于该行的{year}移动向量。因此,猜测值为2016
。
获取给定年份和值向量所需的值很简单:
year <- 2017
year_moved <- c(2010, 2016, 2017)
year_moved[which.min(year-(year_moved[year_moved<year & !is.na(year_moved)]))]
# [1] 2016
rm(year, year_moved)
但是,当我在mutate函数中尝试这个时,它不会给我相同的结果。
df %>%
group_by(id) %>%
mutate(
year_guess = ifelse(moved==1 & is.na(year_moved),
year_moved[which.min(year-(year_moved[year_moved<year]))],
NA))
# # A tibble: 11 x 6
# # Groups: id [2]
# id year house_apt moved year_moved guess
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 11990 2011 1 1 2010 NA
# 2 11990 2015 1 0 NA NA
# 3 11990 2017 2 1 NA NA
# 4 11990 2018 2 1 2016 NA
# 5 11990 2019 2 1 2019 NA
# 6 11990 2020 1 0 NA NA
# 7 22880 2013 1 1 NA 2011
# 8 22880 2014 1 0 2011 NA
# 9 22880 2015 1 1 NA 2011
# 10 22880 2018 2 0 2014 NA
# 11 22880 2020 2 0 1979 NA
# Warning message:
# In year - (year_moved[year_moved < year & !is.na(year_moved)]) :
# longer object length is not a multiple of shorter object length
(第3行应该是2016年,第9行应该是2014年。)我认为部分原因是我无法指定我是否对行值或向量感兴趣。请注意,我第一次引用“year_moved”(is.na(year_moved)
)时,我指的是该行中的值。当我在which.min
中引用它时,我试图引用分组向量。当我提到“年份”时,我试图参考我正在处理的单个行的值。显然,事情有点混乱,这是一个更广泛的问题,我已经遇到了许多不同的应用程序。有人可以提供指导吗?
我一直用tidyverse编写我的整个项目,所以如果可能的话,我想继续。
答案 0 :(得分:1)
我认为修改当前尝试以获得正确结果的最简单方法是将猜测操作包装在sapply
中,以便每年分别计算猜测:
df %>%
group_by(id) %>%
mutate(
year_guess = ifelse(
moved==1 & is.na(year_moved),
sapply(year, function(x) year_moved[which.min(x-(year_moved[year_moved < x]))]),
NA)
)
我还没有能够完全解开其工作原理的逻辑,但我认为编写你的猜测程序有点复杂,很容易被矢量化(尽管如果你稍微接近它可能会不同的方式)。
输出:
# A tibble: 11 x 6
# Groups: id [2]
id year house_apt moved year_moved year_guess
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 11990 2011 1 1 2010 NA
2 11990 2015 1 0 NA NA
3 11990 2017 2 1 NA 2016
4 11990 2018 2 1 2016 NA
5 11990 2019 2 1 2019 NA
6 11990 2020 1 0 NA NA
7 22880 2013 1 1 NA 2011
8 22880 2014 1 0 2011 NA
9 22880 2015 1 1 NA 2014
10 22880 2018 2 0 2014 NA
11 22880 2020 2 0 1979 NA