R语言 根据行中的值筛选并选择数据集



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

我尝试使用 dplyrfilter()select()函数,但由于genderlanguageage都在id列中,因此我无法仅通过键入data %>% filter(gender == 1)进行过滤。

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

我正在尝试做的是找到一种方法,根据年龄、性别和语言值中的值对我的数据进行子集化。假设我想选择性别 1、语言 1 或性别 1 和语言 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))

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

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

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

# 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确保逻辑向量具有所需的长度(列数)。

我建议使用两个数据框,一个(我称之为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 和语言 1 选择所有评级"之类的操作时,您可以对demo进行简单的filter,并联接到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数据框是一个更好的起点。

只需将其侧转即可。请确保先将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