R - 在两组列中搜索两个条件
Posted
技术标签:
【中文标题】R - 在两组列中搜索两个条件【英文标题】:R - search for two conditions across two sets of columns 【发布时间】:2022-01-23 05:39:19 【问题描述】:我有一个名为 fruits 的数据框,其中每行最多有 3 个具有相应颜色的水果。 Color1 与 Fruit1 搭配,Color2 与 Fruit2 搭配,Color3 与 Fruit3 搭配。
Color1 Color2 Color3 Fruit1 Fruit2 Fruit3
1 red green green apple mango kiwi
2 yellow green red banana plum mango
3 green red grape apple
4 yellow apple
使用 dplyr,我可以返回包含苹果的行(1、3 和 4)。我可以返回带有红色(1、2 和 3)的行。
red <- filter_at(fruits, vars(Color1:Color3), any_vars(. == "red"))
apple <- filter_at(fruits, vars(Fruit1:Fruit3), any_vars(. == "apple"))
但是我如何只返回红苹果,即只返回第一行(Color1 = red,Fruit1 = apple)和第三行(Color2 = red,Fruit2 = apple)?
谢谢。
附言这是表格的代码
Color1 <- c("red", "yellow", "green", "yellow")
Color2 <- c("green", "green", "red", "")
Color3 <- c("green", "red", "", "")
Fruit1 <- c("apple", "banana", "grape", "apple")
Fruit2 <- c("mango", "plum", "apple", "")
Fruit3 <- c("kiwi", "mango", "", "")
fruits <- data.frame (Color1, Color2, Color3, Fruit1, Fruit2, Fruit3)
【问题讨论】:
你能用dput(.)
发布你的数据吗?
不是 dput,但这有帮助吗? Color1 <- c("red", "yellow", "green", "yellow") Color2 <- c("green", "green", "red", "") Color3 <- c("green", "red", "", "") Fruit1 <- c("apple", "banana", "grape", "apple") Fruit2 <- c("mango", "plum", "apple", "") Fruit3 <- c("kiwi", "mango", "", "") fruits <- data.frame (Color1, Color2, Color3, Fruit1, Fruit2, Fruit3)
【参考方案1】:
这是使用 tidyverse
/purrr
的替代解决方案:
这将匹配以相同数字结尾的列(即Color1
和Fruit1
、Color20
和Fruit20
)
假设每种颜色都有匹配的水果,否则索引(.[1]
和 .[2]
将失败)。如果需要,您还可以将“red”和“apple”替换为不同的值。
subset_func <- function(data, num)
out <- data %>%
mutate(id = row_number()) %>%
select(id, ends_with(num)) %>%
filter(.[2] == "red" & .[3] == "apple")
data %>%
mutate(id = row_number()) %>%
filter(id %in% out$id) %>%
select(-id)
map_df(as.character(1:3), ~subset_func(fruits, .))
这给了我们:
Color1 Color2 Color3 Fruit1 Fruit2 Fruit3
1 red green green apple mango kiwi
3 green red . grape apple .
【讨论】:
谢谢,我也试试。是的,每种水果都有与之相配的颜色。 抱歉,更新是因为我没有看到第一个版本中出现的NA
。现在它会返回您的完整数据,符合您的条件。
这很好用!现在我可以调整列号以匹配我更大的数据集。非常感谢。【参考方案2】:
我觉得您的数据可能不太理想。 (不是tidy)。
如果您先整理数据,您尝试完成的任务可能会更容易。
library(tidyverse)
Color1 <- c("red", "yellow", "green", "yellow")
Color2 <- c("green", "green", "red", "")
Color3 <- c("green", "red", "", "")
Fruit1 <- c("apple", "banana", "grape", "apple")
Fruit2 <- c("mango", "plum", "apple", "")
Fruit3 <- c("kiwi", "mango", "", "")
fruits <- data.frame (Color1, Color2, Color3, Fruit1, Fruit2, Fruit3)
long_fruits <- fruits %>%
## following r2evans suggestion to include row identifier in order to allow re-pivoting if needed
rownames_to_column("row_id") %>%
pivot_longer(-"row_id", names_to = c(".value", "ID"), names_pattern = "(\\w+)(\\d+)")
long_fruits
#> # A tibble: 12 × 4
#> row_id ID Color Fruit
#> <chr> <chr> <chr> <chr>
#> 1 1 1 "red" "apple"
#> 2 1 2 "green" "mango"
#> 3 1 3 "green" "kiwi"
#> 4 2 1 "yellow" "banana"
#> 5 2 2 "green" "plum"
#> 6 2 3 "red" "mango"
#> 7 3 1 "green" "grape"
#> 8 3 2 "red" "apple"
#> 9 3 3 "" ""
#> 10 4 1 "yellow" "apple"
#> 11 4 2 "" ""
#> 12 4 3 "" ""
long_fruits %>%
filter(Fruit == "apple", Color == "red")
#> # A tibble: 2 × 4
#> row_id ID Color Fruit
#> <chr> <chr> <chr> <chr>
#> 1 1 1 red apple
#> 2 3 2 red apple
由reprex package (v2.0.1) 于 2021 年 12 月 21 日创建
【讨论】:
没错!我正在用这个主题起草我的答案的附件。不错。 我的真实数据框有多达 30 种水果和 30 种相应的颜色,以及其他几列。你还会推荐这种方法吗?就像我需要遍历两组列一样,Fruit1 搜索 Color1,Fruit12 搜索 Color12,等等。 tjebo,能够重建原始框架,或者至少将东西连在一起可能会很好。在透视之前添加行号通常很有用。 Hawkeye214,在我看来,面对这样的数据,我几乎总是会转向更长的格式。我将添加我在之前的评论中提到的“行 ID”,这样我可以在需要时轻松地转回宽格式(例如,用于报告)。它在很大程度上取决于您要对其进行的计算以及您将使用的软件包;一些“需要”长格式或“惩罚”宽格式 (ggplot2
),其他人确实需要宽格式以便于使用。【参考方案3】:
您可以独立处理列集,创建逻辑矩阵,然后将它们与&
进行逻辑组合。
前期:
如果您的数据中有NA
值,则需要一些模组才能正常工作;
这假定所有列的顺序相同;例如,如果您的列的顺序是“Color1, Color2, Color3”和“Fruit3, Fruit2, Fruit1”,那么这将无法正确配对。
假设dplyr
:
select(fruits, starts_with("Color")) == "red"
# Color1 Color2 Color3
# 1 TRUE FALSE FALSE
# 2 FALSE FALSE TRUE
# 3 FALSE TRUE FALSE
# 4 FALSE FALSE FALSE
select(fruits, starts_with("Fruit")) == "apple"
# Fruit1 Fruit2 Fruit3
# 1 TRUE FALSE FALSE
# 2 FALSE FALSE FALSE
# 3 FALSE TRUE FALSE
# 4 TRUE FALSE FALSE
select(fruits, starts_with("Color")) == "red" & select(fruits, starts_with("Fruit")) == "apple"
# Color1 Color2 Color3
# 1 TRUE FALSE FALSE
# 2 FALSE FALSE FALSE
# 3 FALSE TRUE FALSE
# 4 FALSE FALSE FALSE
从这里开始,
fruits %>%
filter(
rowSums(
select(., starts_with("Color")) == "red" &
select(., starts_with("Fruit")) == "apple"
) > 0)
# Color1 Color2 Color3 Fruit1 Fruit2 Fruit3
# 1 red green green apple mango kiwi
# 3 green red . grape apple .
数据。因为我一开始没有你的,所以我首先用.
制作了这个(因为阅读空栏比我最初有时间花费更多的精力)。
fruits <- structure(list(Color1 = c("red", "yellow", "green", "yellow"), Color2 = c("green", "green", "red", "."), Color3 = c("green", "red", ".", "."), Fruit1 = c("apple", "banana", "grape", "apple"), Fruit2 = c("mango", "plum", "apple", "."), Fruit3 = c("kiwi", "mango", ".", ".")), class = "data.frame", row.names = c("1", "2", "3", "4"))
【讨论】:
谢谢,我下次试试。以上是关于R - 在两组列中搜索两个条件的主要内容,如果未能解决你的问题,请参考以下文章
如何编写 R 脚本来检查直线;即,对于任何给定的行,一组列中的所有值是不是具有相同的值