2017-02-15 6 views
1

Я работаю с двумя dataframes в R:Сравнить значения из двух dataframes и слияния

df1 = data.frame(c("A", "B"), c(1, 21), c(17, 29)) 
colnames(df1) = c("location", "start", "stop") 

df1 
location start stop 
A   1  17 
B   21  29 

df2 = data.frame(c("A", "A", "A", "A", "B"), c(1, 10, 20, 40, 20), c(10, 20, 30, 50, 30), c("x1", "x2","x4", "x5", "x3")) 
colnames(df2) = c("location", "start", "stop", "out") 

df2 
location start stop out 
A   1  10  x1 
A   10  20  x2 
A   20  30  x4 
A   40  50  x5 
B   20  30  x3 

Теперь я хочу, чтобы проверить для каждой строки df1:

  • есть матч между " location 'с' location 'от df2
  • , если значение «start» находится в диапазоне начала и остановки от df2 или если значение «end» находится в диапазоне начала и остановки от df2, out "из df2 следует вставить в новый столбец в df1

Это, как результат будет выглядеть в случае данного примера

df1_new 

location start stop out 
A   1  17  x1,x2 
B   21  29  x3 

Я начал в R, но я застрял в точке, где мне нужно, чтобы посмотреть в полный dataframe из df2

for (i in nrow(df1)) { 
    if(df1$location[i] == df2$location # it needs to look for a match in the complete dataframe of df2. I don't know how to do this 
    & if (df1$start[i] %in% # it needs to check if the start value lies in the range between df2$start & df2$end 
} 
+0

Ваша правка очень неполно, вы добавили строки в распечатке , но не для кода, делающего это. Вы также пренебрегли обновлением вывода. – Frank

+0

@Frank: Я забыл изменить код, это сделано сейчас. Выход остается тем же – user1987607

+0

Простите, нет, ваш вход теперь содержит ошибку с кавычками. Попробуйте запустить свой код, прежде чем публиковать его. – Frank

ответ

2

Вот data.table способ, с помощью foverlaps:

library(data.table) 
setkey(setDT(df1)) 
setDT(df2, key = names(df1)) 

foverlaps(df1, df2)[, .(out = toString(out)), by=location] 

# location out 
# 1:  A x1, x2 
# 2:  B  x3 

Вы можете получить другие COLS из foverlaps результатов при желании:

foverlaps(df1, df2) 
# location start stop out i.start i.stop 
# 1:  A  1 10 x1  1  17 
# 2:  A 10 20 x2  1  17 
# 3:  B 20 30 x3  21  29 
+0

спасибо, эта функция foverlaps кажется полезной. Однако что происходит, когда у моего df1 больше столбцов, которые df2. Должен ли я установить ключ только для столбцов, представляющих интерес для df1? – user1987607

+0

@ user1987607 Да. В качестве альтернативы вы можете пропустить клавиши настройки и вместо этого использовать аргументы 'by.x',' by.y' функции. См. '? Foverlaps'. – Frank

2

Вы должны aggregate первый, а затем merge, т.е.

merge(df1, aggregate(out ~ location, df2, toString), by = 'location') 

# location start stop out 
#1  A  1 17 x1, x2 
#2  B 21 29  x3 
+1

Другим вариантом является 'df2%>% group_by (location)%>% summaryize (out = toString (out))%>% inner_join (df1,., By =" location ")' – akrun

+0

@Sotos: я отредактировал мой вопрос немного, потому что вы неправильно поняли вопрос. df2 содержит также строки, в которых начало и остановка не соответствуют значениям в df1. Поэтому в конце df1_new содержит для строки 1 значения «out» из строк 1 и 2 из df2, но не из строк 3 и 4. Это связано с тем, что диапазон начала и остановки равен 1-17, поэтому это перекрывается с линиями 1 и 2 из df2, но не с линиями 3 и 4 – user1987607

Смежные вопросы