Вот подход, основанный на melt
из data.table
. Мы melt
переходим в 'long' формат, основанный на patterns
в именах столбцов (начиная с friend
, bully
), сгруппированных по 'ID', получаем length
из intersect
ing элементов long столбцы набора данных 'value1', 'value2' и сделать соединение on
'ID'
library(data.table)
setDT(df1)[melt(df1, measure = patterns('^friend', '^bully'))[,
.(num_both = length(intersect(value1, value2))), ID], on = .(ID)]
# ID friend_1 friend_2 friend_3 bully_1 bully_2 num_both
# 1: 1 4 12 7 12 15 1
# 2: 2 8 6 7 18 20 0
# 3: 3 9 18 1 2 1 1
# 4: 4 15 7 2 7 13 1
# 5: 5 1 17 9 17 1 2
# 6: 6 9 19 20 14 12 0
# 7: 7 19 12 20 9 12 1
# 8: 8 7 1 16 2 15 0
# 9: 9 1 10 12 1 7 1
#10: 10 7 11 9 11 7 2
Или с помощью tidyverse
путем gather
в формате 'long', сгруппированным по 'ID', summarise
с length
из intersect
элементами 'value', основанными на появлении 'friend' 'или' хулиган 'в столбце' ключ 'и right_join
с исходным набором данных
library(tidyverse)
df1 %>%
gather(key, value, -ID) %>%
group_by(ID) %>%
summarise(num_both = length(intersect(value[str_detect(key, 'friend')],
value[str_detect(key, 'bully')]))) %>%
right_join(df1)
# A tibble: 10 x 7
# ID num_both friend_1 friend_2 friend_3 bully_1 bully_2
# <int> <int> <int> <int> <int> <int> <int>
# 1 1 1 4 12 7 12 15
# 2 2 0 8 6 7 18 20
# 3 3 1 9 18 1 2 1
# 4 4 1 15 7 2 7 13
# 5 5 2 1 17 9 17 1
# 6 6 0 9 19 20 14 12
# 7 7 1 19 12 20 9 12
# 8 8 0 7 1 16 2 15
# 9 9 1 1 10 12 1 7
#10 10 2 7 11 9 11 7
или другой подход, циклически перебирая строки с pmap
df1 %>%
mutate(num_both = pmap(.[-1], ~ c(...) %>%
{length(intersect(.[1:3], .[4:5]))}))
данные
df1 <- structure(list(ID = 1:10, friend_1 = c(4L, 8L, 9L, 15L, 1L, 9L,
19L, 7L, 1L, 7L), friend_2 = c(12L, 6L, 18L, 7L, 17L, 19L, 12L,
1L, 10L, 11L), friend_3 = c(7L, 7L, 1L, 2L, 9L, 20L, 20L, 16L,
12L, 9L), bully_1 = c(12L, 18L, 2L, 7L, 17L, 14L, 9L, 2L, 1L,
11L), bully_2 = c(15L, 20L, 1L, 13L, 1L, 12L, 12L, 15L, 7L, 7L
)), class = "data.frame", row.names = c(NA, -10L))