r - 在调用 mutate() 时引用上一列/下一列
问题描述
我的数据如下所示:
set.seed(1234)
library(tidyverse)
df <- data.frame(Time = c(1,1,2,2,3,3),
Region = c("A", "B", "A", "B", "A", "B"),
Age_1 = round(rnorm(6, mean = 10),0),
Age_2 = round(rnorm(6, mean = 10),0),
Age_3 = round(rnorm(6, mean = 10),0),
Age_4 = round(rnorm(6, mean = 10),0),
Age_5 = round(rnorm(6, mean = 10),0))
我需要为每个区域和时间点生成人口变化比率。例如,Ratio_2
forTime == 2
将是Age_2
(at Time == 2
) / Age_1
(at Time == 1
),按 分组Region
。我可以通过键入以下内容手动执行此操作:
df %>%
group_by(Region) %>%
mutate(Ratio_2 = Age_2 / dplyr::lag(Age_1, order_by = Time),
Ratio_3 = Age_3 / dplyr::lag(Age_2, order_by = Time),
Ratio_4 = Age_4 / dplyr::lag(Age_3, order_by = Time),
Ratio_5 = Age_5 / dplyr::lag(Age_4, order_by = Time))
df
# A tibble: 6 x 11
# Groups: Region [2]
Time Region Age_1 Age_2 Age_3 Age_4 Age_5 Ratio_2 Ratio_3 Ratio_4 Ratio_5
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 A 11 8 9 9 10 NA NA NA NA
2 1 B 10 9 10 10 11 NA NA NA NA
3 2 A 9 10 9 8 12 0.909 1.12 0.889 1.33
4 2 B 9 10 9 9 9 1 1 0.9 0.9
5 3 A 8 11 9 9 12 1.22 0.9 1 1.5
6 3 B 9 9 9 9 9 1 0.9 1 1
由于我的原始数据有很多年龄组,因此此过程涉及大量手动编码。在我看来,程序化解决方案可能如下所示:
df %>%
group_by(Region) %>%
mutate(across(4:7, ~ . / dplyr::lag(.[?], order_by = Time), .names="Ratio_{.col}"))
包含的部分dplyr::lag(.[?])
需要引用数据框中相对于的上一列,.
但我还没有找到这样做的方法。
注意:这个问题与昨天的一篇文章有关,我在这篇文章中试图解决手头的问题,数据是长格式的。不过,以宽格式做是一个不同的问题,这就是我打开这个问题的原因。
解决方案
这是一个选项across
library(dplyr)
library(stringr)
df %>%
group_by(Region) %>%
mutate(across(matches('^Age_[2-5]$'),
~ ./lag(get(str_replace(cur_column(), '\\d+',
as.character(readr::parse_number(cur_column())-1))), order_by = Time ),
.names = "Ratio_{.col}" )) %>%
ungroup
或者可以以简化的方式完成
library(purrr)
df[str_c('Region_', 2:5)] <- map2(df[4:7], df[3:6],
~ .x/lag(.y, order_by = df$Time))
推荐阅读
- scala - 地图火花数据帧上的while循环
- css - 在 Laravel 5.8 中实现分页链接样式错误
- javascript - 当 Animated.View 有一个 Animated.ScrollView 作为孩子时,PanResponder 在 Android 上无法正常工作
- html - 如果我必须将文本拆分为多个 div,我将如何使 text-align 的行为方式与对单个文本的行为方式相同
- python - 使用 Keras fit_generator 训练后保存的模型无法正确给出预测
- java - 覆盖等于和等于之间有什么区别?
- excel - 如何插入一个要求输入日期的输入框,然后在该日期之后添加到行?
- javascript - 如何遍历 JavaScript 中的静态值(常量)列表?
- android - 无法生成用于在 Android Studio 中发布的签名 APK
- html - 在较小的屏幕上更改网格项目的顺序