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 &lt;- c("red", "yellow", "green", "yellow") Color2 &lt;- c("green", "green", "red", "") Color3 &lt;- c("green", "red", "", "") Fruit1 &lt;- c("apple", "banana", "grape", "apple") Fruit2 &lt;- c("mango", "plum", "apple", "") Fruit3 &lt;- c("kiwi", "mango", "", "") fruits &lt;- data.frame (Color1, Color2, Color3, Fruit1, Fruit2, Fruit3) 【参考方案1】:

这是使用 tidyverse/purrr 的替代解决方案:

这将匹配以相同数字结尾的列(即Color1Fruit1Color20Fruit20

假设每种颜色都有匹配的水果,否则索引(.[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】:

您可以独立处理列集,创建逻辑矩阵,然后将它们与&amp; 进行逻辑组合。

前期:

如果您的数据中有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中两个数据框之间的列中的值

如何编写 R 脚本来检查直线;即,对于任何给定的行,一组列中的所有值是不是具有相同的值

算法或 SQL:查找一组列的条件,确保结果集在特定列中的值始终 > 0

在 Pandas 中按列名选择两组列

根据另一列的位置从一组列中返回值

在R中同时估计两个数据集的威布尔分布参数