如何解决如何根据变量匹配检查条件
说我有这些数据:
data <- tibble(person=c("Jack","Jill","Bill"),pet=c("dog","cat","zebra"),pet_cat=c(0,1,0),pet_dog=c(0,1),pet_llama=c(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
的 {{1} } 是 0)。不确定这是否有必要,但一种思考方式是 Jack
指的是 pet
对宠物的偏好,而 person
列指的是宠物的可用性在宠物店,pet_
会告诉此人是否可以购买他们喜欢的宠物。
此外,在某些情况下,不会有 match
列与 pet_
的 person
匹配。在这些情况下,pet
应为 match
。
请注意,对于一个人来说,例如 0
,其他人的值完全无关,Jill
列与 pet_
的 Jill
不对应价值。
这是想要的结果:
pet
我该怎么做?
请注意,我认为这将涉及使用 data_want <- tibble(person=c("Jack",match=c(0,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
。
解决方法
带有 tidyverse
的选项
- 使用
pivot_longer
将其改造成长格式
- 子集
value
为 1 的行 - 通过将 'pet' 中的子字符串与 'name' 列匹配来创建一个逻辑列 -
str_detect
- 按'pet'分组,检查'match'中是否有
any
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
创建一个逻辑向量,即 value 为 1 - 使用逻辑索引对
starts_with
'pet_'` 的列名进行子集化, - 删除子字符串 'pet_' -
str_remove
- 通过连接它们来创建单个字符串 -
str_c
- 移除组属性 (
ungroup
) 并使用str_detect
检测“pet”列值是否与创建的正则表达式模式匹配
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 作为
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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。