【问题标题】:Apply condition to multiple columns with indexing in R将条件应用于具有 R 中索引的多个列
【发布时间】:2021-02-10 01:28:04
【问题描述】:

我有一个很酷的学校作业,我们必须执行一些网络抓取,以抓取 FIFA Ultimate Team (FUT) 中最好的 480 名球员。它们的所有名称和统计信息都存储在数据框中。我们需要创建一个函数,根据玩家的统计数据(例如,玩家的总体评分超过 90)过滤玩家。我创建了以下函数:

player_filter <- function(stats,minimum){
  print(Stats.FUT$Name[Stats.FUT[,stats]>=minimum])
}

参数 'stats' 是一个 1:7 的向量,我想用它来引用我的数据框的列与球员统计数据(1 是整体评分,2 射门,3 运球等等。)

player_filter(1,90) 返回总评分超过 90 的玩家。 player_filter(3,90) 返回运球评分超过 90 的球员。 这很好用。

但是,如果我想查看总和运球评分超过 90 的球员,该功能将失败。

player_filter(c(1,3),90) 为我提供了总评分为 90 的玩家的正确姓名(第 1 列),但为其他玩家返回 NA(第 3 列)。

它似乎不检查第 1 列和第 3 列是否都符合最小值 90,而是检查第一列并忽略(?)第三列。

我做错了什么,为什么?

亲切的问候,

【问题讨论】:

    标签: r indexing conditional-statements


    【解决方案1】:

    我自己找到了方法,但无论如何感谢您的支持。 如果有人遇到过类似的问题,matrixStats 包中的 rowMins 函数提供了一个解决方案。这是一种将单个条件应用于具有索引的多个列的解决方法。下面是一个示例,当我想打印至少有 90 个整体和投篮的球员姓名时(第 1 列和第 3 列)。如下:

    Stats.FUT[,10]

    打印(Stats.FUT$Name[(Stats.FUT[,10] >= 90)

    我希望它在未来的某一天对某人有所帮助。 干杯

    【讨论】:

      【解决方案2】:

      我重新创建了一个(我认为)反映您的格式的数据框:

      library(dplyr)
      #> Warning: package 'dplyr' was built under R version 4.0.3
      #> 
      #> Attaching package: 'dplyr'
      #> The following objects are masked from 'package:stats':
      #> 
      #>     filter, lag
      #> The following objects are masked from 'package:base':
      #> 
      #>     intersect, setdiff, setequal, union
      
      Stats.Fut <- tribble(
        ~names, ~overall, ~shooting,
        "Lionel Messi",90,90,
        "Cristiano Ronaldo",90,90,
        "Neymar",90,90,
        "Kevin De Bruyne",90,90,
        "Robert Lewandowski",90,90,
        "Sadio Mane",90,90,
        "Mohamed Salah",90,90,
        "Kylian Mbappe",90,90,
        "Virgil van Dijk",90,90,
        "Random Player 1",5,5,
        "Random Player 2",6,6
      )
      
      Stats.Fut
      #> # A tibble: 11 x 3
      #>    names              overall shooting
      #>    <chr>                <dbl>    <dbl>
      #>  1 Lionel Messi            90       90
      #>  2 Cristiano Ronaldo       90       90
      #>  3 Neymar                  90       90
      #>  4 Kevin De Bruyne         90       90
      #>  5 Robert Lewandowski      90       90
      #>  6 Sadio Mane              90       90
      #>  7 Mohamed Salah           90       90
      #>  8 Kylian Mbappe           90       90
      #>  9 Virgil van Dijk         90       90
      #> 10 Random Player 1          5        5
      #> 11 Random Player 2          6        6
      

      基础 R 解决方案

      @EricoPatto 的答案基本上是正确的,除了 &amp;&amp; 返回一个布尔值,而 &amp; 返回一个布尔值向量,它将选择正确的名称,如下所示:

      Stats.Fut[, 1][Stats.Fut[, 2] >= 90 & Stats.Fut[, 3] >= 90]
      
      #> [1] "Lionel Messi"       "Cristiano Ronaldo"  "Neymar"            
      #> [4] "Kevin De Bruyne"    "Robert Lewandowski" "Sadio Mane"        
      #> [7] "Mohamed Salah"      "Kylian Mbappe"      "Virgil van Dijk"
      

      要获得这一点,OP 只需替换正确的列索引,如下所示:

      Stats.Fut[, 8][Stats.Fut[, 1] >= 90 & Stats.Fut[, 3] >= 90]
      

      dplyr 解决方案

      执行此操作的更好方法 (IMO) 是使用列名而不是索引。它使代码更易于阅读,并确保即使列重新排序,代码仍将运行。使用 dplyr 和列名,您可以使用以下方法获得相同的解决方案:

      Stats.Fut %>%
        filter(overall >= 90,
               shooting >= 90) %>%
        select(names)
      #> # A tibble: 9 x 1
      #>   names             
      #>   <chr>             
      #> 1 Lionel Messi      
      #> 2 Cristiano Ronaldo 
      #> 3 Neymar            
      #> 4 Kevin De Bruyne   
      #> 5 Robert Lewandowski
      #> 6 Sadio Mane        
      #> 7 Mohamed Salah     
      #> 8 Kylian Mbappe     
      #> 9 Virgil van Dijk
      

      这里的filter 语句实际上是说只返回总分 >= 90 并且投篮得分 >= 90 的行。 这会将名称作为单列小标题返回(基本上是增强的 data.frame)。如果您需要将名称作为向量,请使用 pull 而不是 select,如下所示:

      Stats.Fut %>%
        filter(overall >= 90,
               shooting >= 90) %>%
        pull(names)
      #> [1] "Lionel Messi"       "Cristiano Ronaldo"  "Neymar"            
      #> [4] "Kevin De Bruyne"    "Robert Lewandowski" "Sadio Mane"        
      #> [7] "Mohamed Salah"      "Kylian Mbappe"      "Virgil van Dijk"
      

      【讨论】:

      • 非常感谢丹尼尔的帮助。这不完全是我正在寻找的解决方案,这主要是我自己的错,因为我没有正确总结我的问题。我编辑了我的原始帖子以提供额外的说明。您正确地镜像了我的数据框,我同意您的观点,即使用 deplyr 解决方案的代码更具可读性。只是因为我创建了过滤玩家的函数,所以我需要使用 c(组合)函数来引用这两个列。
      【解决方案3】:

      试试这个:

      Stats.FUT[,8][Stats.FUT[,1]>=90 && Stats.FUT[,3]>=90] 
      

      根据我的经验,这应该很好用。不过,我无法测试它。

      【讨论】:

      • 感谢您的回答 Érico。我认为单个“&”也可以,但这不是我正在寻找的解决方案。我正在寻找一种解决方案,将条件应用于多个列,并使用 c(组合)函数引用它们。
      猜你喜欢
      • 2015-12-28
      • 1970-01-01
      • 2015-02-15
      • 1970-01-01
      • 2013-08-04
      • 2020-04-27
      • 1970-01-01
      • 1970-01-01
      • 2016-05-29
      相关资源
      最近更新 更多