2015-09-16 2 views
0

У меня есть 2 кадра данных, которые мне нужно выполнить.Цитирование и сравнение значений в 2 кадрах данных в R

Df1[1:5,] 

    year month  Vol 
1 2015  7 4.82e-05 
2 2015  6 5.91e-05 
3 2015  5 6.56e-05 
4 2015  4 6.10e-05 
5 2015  3 7.85e-05 

Df2[1:5,] 

    year month IB 
1 2015  7 0 
2 2015  4 1 
3 2015  3 0 
4 2015  6 1 
5 2015  5 0 

мне нужно перебрать DF1, сравнить месяцы с DF1 и DF2, и если они совпадают, то установите DF1$IB<-DF2$IB. Я попытался с помощью sapply, но я получаю эту ошибку

tmp<-sapply(DF1$month,function(x){if(DF2$month==x){ 
DF1$IB<-DF2$IB 
}}) 

Warning messages: 
1: In if (DF2$month == x) { : 
    the condition has length > 1 and only the first element will be used 
..... 

Любая помощь будет принята с благодарностью. В противном случае мне пришлось бы прибегать к нескольким циклам, а так как DF1 имеет длину в 900 тыс. Строк, а DF2 - 300 строк в длину, что кажется мне очень неэффективным.

+4

Вы пробовали 'merge'? – akrun

+1

Что делать, если они не равны? –

ответ

3

С последней версией (see here how to install v1.9.5 from GH) вам не нужно устанавливать ключи и просто нужно setDT(df1)[df2, on = c("year","month")], которые добавить IB, это дает:

year month  Vol IB 
1: 2015  7 4.82e-05 0 
2: 2015  4 6.10e-05 1 
3: 2015  3 7.85e-05 0 
4: 2015  6 5.91e-05 1 
5: 2015  5 6.56e-05 0 

Предположим, что year/month не для обоих наборов данных, вы должны присоединиться к другому:

setDT(df2)[df1, on = c("year","month")] 

, который дает:

year month IB  Vol 
1: 2015  7 0 4.82e-05 
2: 2015  6 1 5.91e-05 
3: 2015  5 0 6.56e-05 
4: 2015  4 1 6.10e-05 
5: 2015  3 NA 7.85e-05 

Используемые данные для второго примера:

df1 <- structure(list(year = c(2015L, 2015L, 2015L, 2015L, 2015L), month = c(7L, 6L, 5L, 4L, 3L), Vol = c(4.82e-05, 5.91e-05, 6.56e-05, 6.1e-05, 7.85e-05)), .Names = c("year", "month", "Vol"), class = "data.frame", row.names = c("1", "2", "3", "4", "5")) 
df2 <- structure(list(year = c(2015L, 2015L, 2015L, 2015L, 2015L), month = c(7L, 4L, 2L, 6L, 5L), IB = c(0L, 1L, 0L, 1L, 0L)), .Names = c("year", "month", "IB"), class = "data.frame", row.names = c("1", "2", "3", "4", "5")) 
+0

Для записи я хорошо знаю особенности 1.9.5. Я принял сознательное решение не использовать их, потому что в этом случае они не нужны (они не улучшают скорость). Кроме того, 1.9.5 нестабилен, и вы не указали, как его установить. – jlhoward

+0

@jlhoward Я не хотел сказать, что вы не знаете v1.9.5. В моем опыте 1.9.5 так же устойчив, как и 1.9.4, более того, он решает довольно некоторые ошибки. Кроме того, я предоставил ссылку на инструкции по установке, но сделаю это более понятным. Следовательно, я не вижу причины для понижения. – Jaap

+0

Позвольте мне сказать так. В тех случаях, когда я прихожу с небольшим улучшением от чужого ответа, я публикую его как комментарий к этому ответу (или предложение) или, в очень редких случаях, и редактирую этот ответ. Вы правы в отношении одной вещи, но это только второй раз, когда я пропустил голосование. Я нахожу практику оскорбительной, но есть пределы. – jlhoward

3

Если ваш Df1 - это то, что большие data.tables могут быть лучше слияния.

library(data.table) 
setkey(setDT(Df1),year,month)[setDT(Df2),IB:=IB] 
Df1 
# year month  Vol IB 
# 1: 2015  3 7.85e-05 0 
# 2: 2015  4 6.10e-05 1 
# 3: 2015  5 6.56e-05 0 
# 4: 2015  6 5.91e-05 1 
# 5: 2015  7 4.82e-05 0 

Так что превращает Df1 в data.table в индексах его на год и месяц, затем делает data.table присоединиться на Df2 (также преобразуется в data.table), затем добавляет IB столбец из Df2 до Df1.

Используя более реалистичный пример:

set.seed(1) 
Df1 <- data.frame(year=rep(2015,1e6), 
        month=sample(3:7,1e6,replace=TRUE), 
        Vol=rnorm(1e6)) 
system.time(result.mrg <- merge(Df1,Df2,by=c("year","month"))) 
# user system elapsed 
# 11.8  0.0 11.8 

system.time(result.dt <- setkey(setDT(Df1),year,month[setDT(Df2),IB:=IB]) 
# user system elapsed 
# 0.07 0.00 0.06 

identical(result.mrg$IB, result.dt$IB) 
# [1] TRUE 
Смежные вопросы