У меня есть такой фрейм данных:
data <- data.frame(family.id=rep(1:6, each=5),
member.id=rep(1:5, times=6),
attribute=c(1, 1, 2, 3, 4, 1, 2, 2, 3, 5, 1, 1, 3, 5, 5, 2,
3, 3, 4, 5, 1, 1, 4, 4, 5, 3, 3, 4, 5, 5))
Я хочу выбрать всех членов домохозяйства, если хотя бы один из них имеет атрибут, равный 4. скажите пожалуйста, что мне делать?
Я предпочитаю использовать команду «group_by» из dplyr.
library(tidyverse)
data %>%
filter(any(attribute == 4), .by = family.id)
или
data %>%
group_by(family.id) %>%
filter(any(attribute == 4)) %>%
ungroup()
family.id member.id attribute
1 1 1 1
2 1 2 1
3 1 3 2
4 1 4 3
5 1 5 4
6 4 1 2
7 4 2 3
8 4 3 3
9 4 4 4
10 4 5 5
11 5 1 1
12 5 2 1
13 5 3 4
14 5 4 4
15 5 5 5
16 6 1 3
17 6 2 3
18 6 3 4
19 6 4 5
20 6 5 5
Вы можете использовать subset
+ ave
, если используете основание R.
> subset(data, ave(attribute == 4, family.id) > 0)
family.id member.id attribute
1 1 1 1
2 1 2 1
3 1 3 2
4 1 4 3
5 1 5 4
16 4 1 2
17 4 2 3
18 4 3 3
19 4 4 4
20 4 5 5
21 5 1 1
22 5 2 1
23 5 3 4
24 5 4 4
25 5 5 5
26 6 1 3
27 6 2 3
28 6 3 4
29 6 4 5
30 6 5 5
ave
или subset
:
data[as.logical(with(data, ave(attribute, family.id, FUN = \(x) any(x==4L)))), ]
# or
subset(data, family.id %in% unique(family.id[attribute==4L]))
В базе должен быть более лаконичный вариант, пока не вспомнил.
Я думаю, что вариант subset
лучший. Не уверен, почему это должна быть операция group/ave/by, поскольку вы можете напрямую выбрать family.id
и избавиться от необходимости явного выполнения цикла.
Используя any
в subset
,
> subset(data, ave(attribute == 4, family.id, FUN=any))
family.id member.id attribute
1 1 1 1
2 1 2 1
3 1 3 2
4 1 4 3
5 1 5 4
16 4 1 2
17 4 2 3
18 4 3 3
19 4 4 4
20 4 5 5
21 5 1 1
22 5 2 1
23 5 3 4
24 5 4 4
25 5 5 5
26 6 1 3
27 6 2 3
28 6 3 4
29 6 4 5
30 6 5 5
кронштейны,
> data[with(data, family.id %in% family.id[attribute == 4]), ]
family.id member.id attribute
1 1 1 1
2 1 2 1
3 1 3 2
4 1 4 3
5 1 5 4
16 4 1 2
17 4 2 3
18 4 3 3
19 4 4 4
20 4 5 5
21 5 1 1
22 5 2 1
23 5 3 4
24 5 4 4
25 5 5 5
26 6 1 3
27 6 2 3
28 6 3 4
29 6 4 5
30 6 5 5
Таблица данных,
> library(data.table)
> setDT(data)[family.id %in% family.id[attribute == 4], ]
family.id member.id attribute
<int> <int> <num>
1: 1 1 1
2: 1 2 1
3: 1 3 2
4: 1 4 3
5: 1 5 4
6: 4 1 2
7: 4 2 3
8: 4 3 3
9: 4 4 4
10: 4 5 5
11: 5 1 1
12: 5 2 1
13: 5 3 4
14: 5 4 4
15: 5 5 5
16: 6 1 3
17: 6 2 3
18: 6 3 4
19: 6 4 5
20: 6 5 5
family.id member.id attribute
или
> setDT(data)[, if (4 %in% attribute) .SD, by = family.id]
family.id member.id attribute
<int> <int> <num>
1: 1 1 1
2: 1 2 1
3: 1 3 2
4: 1 4 3
5: 1 5 4
6: 4 1 2
7: 4 2 3
8: 4 3 3
9: 4 4 4
10: 4 5 5
11: 5 1 1
12: 5 2 1
13: 5 3 4
14: 5 4 4
15: 5 5 5
16: 6 1 3
17: 6 2 3
18: 6 3 4
19: 6 4 5
20: 6 5 5
family.id member.id attribute
Огромное спасибо, Юрий, за ответ. Буду признателен, если вы скажете, как я могу это сделать с помощью "group_by".