#r #dataframe
#r #фрейм данных
Вопрос:
У меня есть фрейм данных, который содержит три столбца, и второй, который содержит два столбца.
df1 <- data.frame(X1 = c('A', 'A', 'A', 'A', 'A', 'A', 'B'),
X2 = c('B', 'B', 'B', 'C', 'C', 'D', 'C'),
X3 = c('C', 'D', 'E', 'D', 'E', 'E', 'D'))
df2 <- data.frame(X1 = c('A', 'A'),
X2 = c('B', 'D'))
Вопросы:
- Как мне найти строки, в
df1
которых содержатся все элементы строкиdf2
? т.е. строки 1: 3df1
содержат обаA
иB
(первая строкаdf2
). Я ищу, чтобы удалить любые строкиdf1
, которые содержат оба элемента строкdf2
. Итак, в примере я хотел бы удалить строки 1, 2, 3, 4 и 6df1
, поскольку они включаютA
иB
ИЛИA
иD
. - Есть ли быстрый способ подсчитать количество строк для каждой строки
df2
без зацикливания? т.е.df2
строка 1 будет иметь количество 3, а строка 2 — количество 3.
Ответ №1:
Вот базовая опция R, использующая outer
intersect
mat <- lengths(
outer(
asplit(df1, 1),
asplit(df2, 1),
Vectorize(intersect)
)
) >= ncol(df2)
и вы получите
> subset(df1, !rowSums(mat))
X1 X2 X3
5 A C E
7 B C D
> within(df2, cnt <- colSums(mat))
X1 X2 cnt
1 A B 3
2 A D 3
asplit
разбивает фреймы данных по строкамouter
создает все комбинации строк изdf1
иdf2
intersect
выдает пересекающиеся элементы строк из двух фреймов данныхsubset
выбирает строки, в которых меньше одного общего элемента
Ответ №2:
С помощью apply:
df1[ !apply(df1, 1, function(i) any(apply(df2, 1, function(j) all(j %in% i)))), ]
# X1 X2 X3
# 5 A C E
# 7 B C D
Выполните аналогичные циклы для подсчета совпадений df2:
cbind(df2,
cnt = apply(df2, 1, function(i) sum(apply(df1, 1, function(j) all(i %in% j)))))
# X1 X2 cnt
# 1 A B 3
# 2 A D 3
Ответ №3:
Вам нужно как-то выполнить цикл. Вот один из способов сделать это с помощью dplyr
и purrr
:
1.
for(iRow in seq_len(nrow(df2))){
df1 <- df1 %>%
rowwise() %>%
filter(!all(as.character(df2[iRow,]) %in% c_across(everything())))
}
2.
df2 %>%
rowwise() %>%
mutate(n = sum(map_int(transpose(df1), ~all(c_across(everything()) %in% .x))))
Просто не забудьте выполнить 2-ю часть перед 1-й, потому что 1-я часть удаляет строки. Также вы можете сначала определить, какие строки нужно удалить для каждой строки df2
. Таким образом, вы можете посчитать их, а затем удалить.
df2 <- df2 %>%
rowwise() %>%
mutate(
indices = list(which(map_lgl(transpose(df1), ~all(c_across(everything()) %in% .x))))
) %>%
ungroup() %>%
mutate(n = map_int(indices, length))
df1 <- df2[["indices"]] %>%
unlist() %>%
unique() %>%
"*"(-1) %>%
df1[.,]
df2 <- df2 %>% select(-indices)