Мы расширяем данные, разделяя в ;
Targets.missed в «длинный» формат, затем группируем по «Shooter», summarise
с list
числами, которых нет в ' Targets.missed 'из 1:10, unnest
столбец list
, сгруппированный по' Target ', summarise
по paste
, объединяющий элементы unique
' Shooter 'в одну строку и заполняющий недостающие элементы от 1:10 с NA
с помощью complete
library(tidyverse)
mydf %>%
separate_rows(Targets.missed) %>%
group_by(Shooter) %>%
summarise(Target = list(setdiff(1:10, Targets.missed))) %>%
unnest %>%
group_by(Target) %>%
summarise(hit.by.Shooters = paste(unique(Shooter), collapse=";")) %>%
complete(Target = 1:10)
# A tibble: 10 x 2
# Target hit.by.Shooters
# <int> <chr>
# 1 1 1
# 2 2 1;2;3
# 3 3 2;3
# 4 4 <NA>
# 5 5 1
# 6 6 1;2
# 7 7 <NA>
# 8 8 2
# 9 9 1;2
#10 10 1
Или другой вариант - base R
путем разделения 'Targets.missed' (при условии character
class) на list
из vector
s, цикл по list
, получение значений, которые не находятся в 1:10 (с setdiff
), задайте имена list
в столбце Shooter, stack
пары ключ / val list
в два столбца data.frame, получите строки unique
, aggregate
с помощью paste
в столбце 'ind', сгруппированном по 'values', merge
с полным набором данных 'values' от 1:10
out <- aggregate(ind ~ values,
unique(stack(setNames(lapply(strsplit(mydf$Targets.missed, ';'),
setdiff, x= 1:10), mydf$Shooter))), FUN = paste, collapse=";")
out1 <- merge(data.frame(values = 1:10), out, all.x = TRUE)
и при необходимости измените имена столбцов
names(out1) <- c('Target', 'hit.by.Shooters')
данные
mydf <- structure(list(Shooter = 1:3, Targets.missed = c("3;8;4;7", "10;1;5;7;4",
"5;9;4;10;8;1;6;7")), class = "data.frame", row.names = c("1",
"2", "3"))