r - 如何根据变量匹配检查条件
问题描述
假设我有这些数据:
data <- tibble(person=c("Jack", "Jill", "Bill"), pet=c("dog", "cat", "zebra"), pet_cat=c(0,1,0), pet_dog=c(0,1,1), pet_llama=c(1,1,1))
person pet pet_cat pet_dog pet_llama
<chr> <chr> <dbl> <dbl> <dbl>
1 Jack dog 0 0 1
2 Jill cat 1 1 1
3 Bill zebra 0 1 1
我想要做的是,对于每个人,首先找出他们拥有的宠物(杰克有一只狗),然后转到包含此宠物的列(对于杰克,这是pet_dog
列)。然后创建一个新列,match
复制列中的值pet_
(对于 Jack,这是0
因为pet_dog
的值为Jack
0)。不确定这是否有必要,但考虑这一点的一种方式是pet
指 对person
宠物的偏好,pet_
列指宠物商店中宠物的可用性,并match
说明该人是否能够购买他们喜欢的宠物。
此外,在某些情况下,不会有与'spet_
匹配的列。在这些情况下,应该是.person
pet
match
0
请注意,对于一个人,比如说Jill
,其他人的值是完全不相关的,pet_
不对应于Jill
的pet
值的列也是如此。
这是期望的结果:
data_want <- tibble(person=c("Jack", "Jill", "Bill"), pet=c("dog", "cat", "zebra"), pet_cat=c(0,1,0), pet_dog=c(0,1,1), pet_llama=c(1,1,1), match=c(0, 1, 0))
person pet pet_cat pet_dog pet_llama match
<chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Jack dog 0 0 1 0
2 Jill cat 1 1 1 1
3 Bill zebra 0 1 1 0
我怎样才能做到这一点?
请注意,我认为这将涉及使用类似或组合的pet
东西将人的值放入变量中,然后转到此列并提取相关值并将其放入。get
assign
paste0
match
解决方案
一个选项tidyverse
- 重塑为长格式
pivot_longer
value
对1的行进行子集化- 通过将 'pet' 中的子字符串与 'name' 列匹配来创建一个逻辑列 -
str_detect
- 按'pet'分组,检查
any
'match'中是否有TRUE,强制转换为二进制(+
) - 加入原始数据集 -
right_join
- 如果我们想保留原始数据的顺序,请创建一个序列列 (
row_number()
) 并对行进行排序 (arrange
)
library(dplyr)
library(tidyr)
library(stringr)
data %>%
pivot_longer(cols = contains('_')) %>%
filter(value == 1) %>%
mutate(match = str_detect(name, pet)) %>%
group_by(pet) %>%
summarise(match = +(any(match))) %>%
right_join(data %>%
mutate(rn = row_number())) %>%
arrange(rn) %>%
select(names(data), match)
-输出
# A tibble: 3 x 6
person pet pet_cat pet_dog pet_llama match
<chr> <chr> <dbl> <dbl> <dbl> <int>
1 Jack dog 0 0 1 0
2 Jill cat 1 1 1 1
3 Bill zebra 0 1 1 0
或者可以使用rowwise
- 创建
rowwise
属性 - 按行分组 - 用于
c_across
创建逻辑向量,即值为 1 starts_with
使用逻辑索引子集'pet_'`的列名,- 删除子字符串 'pet_' -
str_remove
- 通过连接它们创建单个字符串 -
str_c
- 删除组属性 (
ungroup
) 并用于str_detect
检测“宠物”列值是否与创建的正则表达式模式匹配
data %>%
rowwise %>%
mutate(match = str_c(str_remove(names(select(cur_data(),
contains('_')))[c_across(contains("_")) == 1], ".*_"),
collapse="|")) %>%
ungroup %>%
mutate(match = +(str_detect(pet, match)))
# A tibble: 3 x 6
person pet pet_cat pet_dog pet_llama match
<chr> <chr> <dbl> <dbl> <dbl> <int>
1 Jack dog 0 0 1 0
2 Jill cat 1 1 1 1
3 Bill zebra 0 1 1 0
或使用base R
- 选择包含 'pet_' (nm1) 的列名
- 根据行序列创建行/列索引,并
match
使用“pet”列创建列名的子字符串 - 使用 2 作为 a 从选定的数据列中获取相应的元素
matrix
- 将 NA(即不匹配)的元素替换为 0
nm1 <- names(data)[startsWith(names(data), "pet_")]
data$match <- as.data.frame(data[nm1])[cbind(seq_len(nrow(data)),
match(data$pet, sub("pet_", "", nm1)))]
data$match[is.na(data$match)] <- 0
-输出
data
# A tibble: 3 x 6
person pet pet_cat pet_dog pet_llama match
<chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Jack dog 0 0 1 0
2 Jill cat 1 1 1 1
3 Bill zebra 0 1 1 0
推荐阅读
- html - Html 表 - td 宽度百分比,溢出不起作用
- jekyll - Jekyll 布局在错误的目录中查找
- wordpress - 如何将 TarteAuCitron (RGPD / ePR) 与 ContactForm7 集成的 reCAPTCHA 结合使用?
- php - PHP:带有空键的 http_build_query 多维数组
- xml - 将原生 DDS 系统与 ROS2 连接
- node.js - 如何使用替代配置从同一文件夹运行第二个 node.js 服务器
- python-3.6 - 为 python3 构建张量流/服务失败
- tableau-api - 将 Tableau 筛选器与地图一起使用 - 始终包含一个值,但将其从筛选器中排除
- javascript - Node/Webpack/javascript es6 - 在 Object.Assign() 内的要求上添加条件
- c++ - 如何使用条件变量使睡眠线程不会错过唤醒呼叫?