r - R:将 mutate 调用从处理三个二进制变量调整为 n 个二进制变量
问题描述
我有一个数据框,其中包含与时间段 1 相关的 3 个二进制变量和与时间段 2 相关的三个相应变量。
df <- data.frame("user" = c("a","b","c","d","e"), "item_1_time_1" = c(1,0,0,0,NA), "item_2_time_1" = c(1,1,1,0,NA), "item_3_time_1" = c(0,0,1,0,0), "item_1_time_2" = c(1,0,0,0,NA), "item_2_time_2" = c(1,0,0,0,NA), "item_3_time_2" = c(0,0,1,0,1))
df
user item_1_time_1 item_2_time_1 item_3_time_1 item_1_time_2 item_2_time_2 item_3_time_2
1 a 1 1 0 1 1 0
2 b 0 1 0 0 0 0
3 c 0 1 1 0 0 1
4 d 0 0 1 0 0 0
5 e NA NA 0 NA NA 1
我想知道观察是否在第 1 期但在第 2 期没有1
给定item
。此外,我想知道观察是否有任何实例,其中项目1
在第 1 期而不是第 2 期。
所以理想的输出看起来像
df2 <- data.frame("user" = c("a","b","c","d","e"), "item_1_time_1" = c(1,0,0,0,NA), "item_2_time_1" = c(1,1,1,0,NA), "item_3_time_1" = c(0,0,1,1,0), "item_1_time_2" = c(1,0,0,0,NA), "item_2_time_2" = c(1,0,0,0,NA), "item_3_time_2" = c(0,0,1,0,1), "item_1_check" = c(1,1,1,1,1), "item_2_check" = c(1,0,0,1,1), "item_3_check" = c(1,1,1,0,1), item_check = c(1,0,0,0,1))
df2
user item_1_time_1 item_2_time_1 item_3_time_1 item_1_time_2 item_2_time_2 item_3_time_2 item_1_check item_2_check item_3_check item_check
1 a 1 1 0 1 1 0 1 1 1 1
2 b 0 1 0 0 0 0 1 0 1 0
3 c 0 1 1 0 0 1 1 0 1 0
4 d 0 0 1 0 0 0 1 1 0 0
5 e NA NA 0 NA NA 1 1 1 1 1
到目前为止我已经尝试过
library(tidyverse)
df2 <- df %>%
mutate(across(ends_with('time_2'), replace_na, 0)) %>%
mutate(across(ends_with('time_1'), replace_na, 0)) %>%
mutate(item_1_check = if_else(item_1_time_1 == 1 & item_1_time_2 == 0, 0, 1),
item_2_check = if_else(item_2_time_1 == 1 & item_2_time_2 == 0, 0, 1),
item_3_check = if_else(item_3_time_1 == 1 & item_3_time_2 == 0, 0, 1)) %>%
mutate(item_check = pmin(item_1_check, item_2_check, item_3_check))
我想概括上述 mutate 调用,以便它们可以处理 n 个项目,而不仅仅是 3个。 有没有一种方法可以ends_with('check')
用于最终的 mutate?变量名称没有变化,但项目编号和时间段不同。
解决方案
一种选择是重塑为“长”格式并执行一次
library(dplyr)
library(tidyr)
df %>%
pivot_longer(cols = -user, names_to = c('group', '.value'),
names_sep="_(?=time)") %>%
mutate(across(starts_with('time'), replace_na, 0)) %>%
group_by(group) %>%
transmute(user, check = !(time_1 & !time_2)) %>%
ungroup %>%
group_by(user) %>%
summarise(check = min(check), .groups = 'drop') %>%
right_join(df, .) %>%
select(names(df), check)
# user item_1_time_1 item_2_time_1 item_3_time_1 item_1_time_2 item_2_time_2 item_3_time_2 check
#1 a 1 1 0 1 1 0 1
#2 b 0 1 0 0 0 0 0
#3 c 0 1 1 0 0 1 0
#4 d 0 0 0 0 0 0 1
#5 e NA NA 0 NA NA 1 1
或使用base R
df$check <- +( Reduce(`&`, lapply(split.default(replace(df[-1],
is.na(df[-1]), 0), sub("time_\\d+", "", names(df)[-1])),
function(x) !(x[[1]] & !x[[2]]))))
推荐阅读
- c - 如何创建一个从 99% 倒计时到 0% 的计时器,每秒减少 1%
- python - 从 cassandra 获取所有数据
- bash - 用于在其中包含 .git 目录的所有子文件夹中进行 git pull 的代码的 if 语句问题
- android - 如何修复错误:找不到 recyclerview-v7.jar (com.android.support:recyclerview-v7:28.0.0)
- java - 如何从 onClickListener 之外的 onClickListener 获取值
- matlab - 重命名子系统的输入和输出
- excel - 如何通过 Excel VBA 修改 Powerpoint Chart ChartData
- gensim - gensim/models/ldaseqmodel.py:217:RuntimeWarning:在 double_scalars 中遇到除以零
- python - 图例仅出现在 1 行的全息视图中
- amazon-web-services - 在 Cognito 用户池中注册时如何检查用户是否已经存在具有相同的电子邮件或电话号码