R найти перекрытие между строками в столбцах двух фреймов данных - PullRequest
3 голосов
/ 07 апреля 2020

У меня есть следующие кадры данных df1 и df2. Это всего лишь примеры, мои настоящие данные имеют около 1000 строк и 10 столбцов.

df1 = data.frame(V1 = c(1,2), V2 = c("a, b, d", "c, g"))

> df1
  V1         V2
1  1    a, b, d
2  2       c, g

df2 = data.frame(V3 = c(1,2,3), V4 = c("a, c", "b, e", "a, g"))

> df2
  V3      V4
1  1    a, c
2  2    b, e
3  3    a, g

Как видите, столбцы V2 и V4 содержат значения, разделенные ", ".

I Теперь я хочу провести l oop через мой df1 строка за строкой и проверить, совпадает ли какое-либо из значений, присутствующих в V2, с одним из значений, присутствующих в V4. Поэтому я не хочу сравнивать все содержимое столбца, но значение на значение.

Вот так должен выглядеть мой вывод df3

df3 = data.frame(V1 = c(1, 1, 1, 2, 2), V2 = c("a, b, d", "a, b, d", "a, b, d", "c, g", "c, g"), V5 = c("a","a","b","c","g"), V3 = c(1, 3, 2, 1, 3), V4 = c("a, c","a, g", "b, e", "a, c", "a, g"), V6 = c("a", "a","b", "c", "g"))

> df3
  V1      V2 V5 V3   V4 V6
1  1 a, b, d  a  1 a, c  a
2  1 a, b, d  a  3 a, g  a
3  1 a, b, d  b  2 b, e  b
4  2    c, g  c  1 a, c  c
5  2    c, g  g  3 a, g  g

Давайте посмотрим на первую строку df1 , В V2 есть значения «a», «b» и «d». Мы начинаем с «а» и смотрим в df2, если «а» присутствует в V4. Это верно для строк 1 и 3 df2. Мы создаем две строки в выводе df3. Строка 1 содержит информацию о первом совпадении: исходные столбцы V1, V2, V3 и V4 + 2 новых столбца V5 и V6, которые содержат совпадающее значение «a» из df1 и df2 соответственно.

Надеюсь, это понятно.

Я бы начал с for для l oop, и я подумал, что может потребоваться разделить мои столбцы V2 на ',', но я не уверен это необходимо.

for (row in 1:nrow(df1)) {
 // split col V2 of df1 by ','
 // if V2 %in% in df2$V4 ...
}

Ответы [ 3 ]

3 голосов
/ 07 апреля 2020

Используйте separate_rows, чтобы разделить свернутый столбец на df1 и df2, и объедините их вместе с inner_join.

library(dplyr)
library(tidyr)

df.a <- df1 %>%
  mutate(V5 = V2) %>% 
  separate_rows(V5)

df.b <- df2 %>%
  mutate(V6 = V4) %>% 
  separate_rows(V6)

inner_join(df.a, df.b, c("V5" = "V6"))

#   V1      V2 V5 V3   V4
# 1  1 a, b, d  a  1 a, c
# 2  1 a, b, d  a  3 a, g
# 3  1 a, b, d  b  2 b, e
# 4  2    c, g  c  1 a, c
# 5  2    c, g  g  3 a, g
1 голос
/ 07 апреля 2020

Вот еще одно решение, которое преобразует в long, а затем выполняет слияние, теперь с data.table

## Convert to data.table with character columns (rather than factor)
library(data.table)
setDT(df1)[, V2 := as.character(V2)]
setDT(df2)[, V4 := as.character(V4)]

## Find common elements
common <- 
  merge(
    df1[, .(V5 = strsplit(V2, ', ')[[1]]), V1],
    df2[, .(V5 = strsplit(V4, ', ')[[1]]), V3])

common
#    V5 V1 V3
# 1:  a  1  1
# 2:  a  1  3
# 3:  b  1  2
# 4:  c  2  1
# 5:  g  2  3

## Merge back to original data
merge(merge(common, df1, by = 'V1'), df2, by = 'V3')
#    V3 V1 V5      V2   V4
# 1:  1  1  a a, b, d a, c
# 2:  1  2  c    c, g a, c
# 3:  2  1  b a, b, d b, e
# 4:  3  1  a a, b, d a, g
# 5:  3  2  g    c, g a, g

Последний шаг также может быть записан как reduce, а не как множественные явные вызовы * 1005. *

## Merge back to original data
purrr::reduce2(list(df1, df2), c('V1', 'V3'), merge, .init = common)
#    V3 V1 V5      V2   V4
# 1:  1  1  a a, b, d a, c
# 2:  1  2  c    c, g a, c
# 3:  2  1  b a, b, d b, e
# 4:  3  1  a a, b, d a, g
# 5:  3  2  g    c, g a, g
1 голос
/ 07 апреля 2020

Вот базовое решение R с использованием merge + strsplit

df3 <- within(merge(df1,df2),
              V5 <- unlist(Map(function(x,y) ifelse(length(u <- intersect(x,y)),u,NA),
                               strsplit(as.character(V2),", "),
                               strsplit(as.character(V4),", "))))


df3 <- (df3 <- subset(df3,complete.cases(df3)))[order(df3$V1),]

таким, что

> df3
  V1      V2 V3   V4 V5
1  1 a, b, d  1 a, c  a
3  1 a, b, d  2 b, e  b
5  1 a, b, d  3 a, g  a
2  2    c, g  1 a, c  c
6  2    c, g  3 a, g  g
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...