【问题标题】:Filter and select a dataset based on a value in a row根据行中的值过滤和选择数据集
【发布时间】:2019-10-22 17:40:25
【问题描述】:

我研究了 dplyr 和 tidyr 甚至是 base R,但我似乎无法弄清楚如何根据行值对我的数据进行子集化。

我曾尝试使用 dplyr filter()select() 函数,但因为 genderlanguageageid 列中,我无法仅通过键入 data %>% filter(gender == 1) 进行过滤。

我有一个包含 50 位评估者的列表。对于此处的示例,我将显示 5。我有 183 行,其中包括评估者对每个问题的回答,最后三行包含人口统计数据,例如年龄、性别以及某人是母语还是非母语。我这里以6行为例进行说明。

我想做的是找到一种方法,根据年龄、性别和语言值中的值对我的数据进行子集化。假设我想选择性别 1、语言 1 或性别 1 AND 语言 1 的所有评分。

谢谢。

代码:

data <- data.frame("id" = c(901,902,903,"age",
                                        "gender",
                                        "language"), 
                   "rater1" = c(7, 9, 9, 21, 1, 1),
                   "rater2" = c(9, 9, 9, 39, 2, 2),
                   "rater3" = c(9, 9, 9, 38, 2, 1),
                   "rater4" = c(9, 9, 9, 33, 2, 1),
                   "rater5" = c(2, 9, 9, 21, 2, 1))

【问题讨论】:

  • 尝试library(tidyverse) 然后 filter()
  • 查看dolyr::filter
  • 请展示您尝试过但没有奏效的方法。否则很难知道答案的目标位置。
  • @Gregor 我尝试使用 dplyr,但使用过滤器无济于事。我会更新我的帖子。
  • 前3个id,901、902、903是什么意思?这些是评估者回应的问题 ID 吗?

标签: r dplyr tidyr


【解决方案1】:

为了按性别和其他感兴趣的变量进行过滤,我们需要重新排列数据,使它们成为列而不是列中的行。我们可以做到这一点的一种方法是使用收集然后传播。更改结构后,您可以使用 dplyr 过滤。

data <- data %>% 
  gather("Rater",rater1:rater5, value = "Value") %>% 
  spread(id, value = Value) %>% 
  filter(gender == 1)

【讨论】:

    【解决方案2】:

    好吧,我不确定这是否适合您的用例,但您可以进行基本索引:

    # data
    x <- data.frame("id" = c(901,902,903,"age","gender","language"), 
                       "rater1" = c(7, 9, 9, 21, 1, 1),
                       "rater2" = c(9, 9, 9, 39, 2, 2),
                       "rater3" = c(9, 9, 9, 38, 2, 1),
                       "rater4" = c(9, 9, 9, 33, 2, 1),
                       "rater5" = c(2, 9, 9, 21, 2, 1))
    
    # ensure id is character and not factor
    x$id <- as.character(x$id)
    
    # select all raters whose gender or language is 1
    x[, c(TRUE, x[x$id == "gender", -1] == 1) |
        c(TRUE, x[x$id == "language", -1] == 1) ]
    

    TRUE 确保在任何情况下都保留 id 列,-1 确保逻辑向量具有所需的长度(列数)。

    【讨论】:

      【解决方案3】:

      我建议使用两个数据框,一个(我称为 demo)用于评估者的人口统计信息,每个评估者 1 行,一个(我称为评级)用于每个评估者给出的评级,每个评估者 1 行回复:

      library(tidyr)
      library(dplyr)
      demo = tail(data, 3)
      ratings = head(data, -3)
      
      demo_cols = demo$id
      demo = data.frame(t(demo[-1]))
      names(demo) = demo_cols
      demo$rater = as.numeric(sub(pattern = "rater", replacement = "", rownames(demo)))
      demo
      #        age gender language rater
      # rater1  21      1        1     1
      # rater2  39      2        2     2
      # rater3  38      2        1     3
      # rater4  33      2        1     4
      # rater5  21      2        1     5
      
      ratings = tidyr::pivot_longer(ratings, cols = starts_with("rater"),
                                    names_to = "rater", names_prefix = "rater") %>%
        mutate(rater = as.numeric(rater))
      ratings
      # # A tibble: 15 x 3
      #    id    rater value
      #    <fct> <dbl> <dbl>
      #  1 901   1         7
      #  2 901   2         9
      #  3 901   3         9
      #  4 901   4         9
      #  5 901   5         2
      #  6 902   1         9
      #  ...
      

      然后,当您想要执行类似 “选择性别 1、语言 1 或性别 1 AND 语言 1 的所有评分”之类的操作时,您可以执行简单的filter of demo,并加入ratings数据得到匹配记录:

      demo %>% filter(gender == 1 & language == 1) %>%
        inner_join(ratings)
      # Joining, by = "rater"
      #   age gender language rater  id value
      # 1  21      1        1     1 901     7
      # 2  21      1        1     1 902     9
      # 3  21      1        1     1 903     9
      

      您也可以进行完全连接 ratings_with_demo = inner_join(ratings, demo) 并直接过滤该数据框。但请记住,如果您这样做,每一行都是一个响应。如果你想做一些事情,比如按gender 计算评分者的数量,demo 数据框是一个更好的起点。

      【讨论】:

        【解决方案4】:

        只需将其侧放即可。确保先将id 转换为行名,然后删除id 以防止类型强制。 t 还返回一个矩阵,因此您需要使用as_tibbleas.data.frame 将数据转回数据框:

        library(dplyr)
        data <- as_tibble(t(`rownames<-`(data, data$id)[-1]))
        

        现在filter 应该会如你所愿:

        data %>% filter(gender == 1)
        
        #### OUTPUT ####
        
        # A tibble: 1 x 6
          `901` `902` `903`   age gender language
          <dbl> <dbl> <dbl> <dbl>  <dbl>    <dbl>
        1     7     9     9    21      1        1
        

        【讨论】:

          猜你喜欢
          • 2017-05-24
          • 2012-10-23
          • 2021-03-08
          • 1970-01-01
          • 1970-01-01
          • 2016-10-14
          • 1970-01-01
          • 2021-12-04
          • 2020-10-09
          相关资源
          最近更新 更多