は、私は2つのデータフレームそうのようにあります:私は(all.x=T
付き)df
にto.merge
をマージしたいR - A、B、*に最も近い* C *のデータフレームをマージしますか?
set.seed(1)
df <- cbind(expand.grid(x=1:3, y=1:5), time=round(runif(15)*30))
to.merge <- data.frame(x=c(2, 2, 2, 3, 2),
y=c(1, 1, 1, 5, 4),
time=c(17, 12, 11.6, 22.5, 2),
val=letters[1:5],
stringsAsFactors=F)
よう:
df$x == to.merge$x
とdf$y == to.merge$y
とabs(df$time - to.merge$time) <= 1
。満足する複数のto.merge
の場合、この距離を最小にするものを選ぶ。
どうすればいいですか?
だから、私の所望の結果(これはちょうど一致する行のために添加to.merge
の対応value
列とdf
)である:
x y time val
1 1 1 8 NA
2 2 1 11 c
3 3 1 17 NA
4 1 2 27 NA
5 2 2 6 NA
6 3 2 27 NA
7 1 3 28 NA
8 2 3 20 NA
9 3 3 19 NA
10 1 4 2 NA
11 2 4 6 NA
12 3 4 5 NA
13 1 5 21 NA
14 2 5 12 NA
15 3 5 23 d
to.merge
た:
x y time val
1 2 1 17.0 a
2 2 1 12.0 b
3 2 1 11.6 c
4 3 5 22.5 d
5 2 4 2.0 e
注 - (2 (X、Y)=(2,1)の場合、time
17がdf$time
11から1以上離れていたため、df
に一致しませんでした。 。
はまた、そこdf
に一致させるための条件を満たしto.merge
に2列であった年代(2、1、11)行が、しかし 『そのtime
であったため、C B『列』行が代わりに選ばれました』最後に、to.merge
には、df
に一致しない行が存在する可能性があります。to.merge
には、df
の何も一致しません。私はと感じてい
df$value <- NA
for (i in 1:nrow(df)) {
row <- df[i, ]
idx <- which(row$x == to.merge$x &
row$y == to.merge$y &
abs(row$time - to.merge$time) <= 1)
if (length(idx)) {
j <- idx[which.min(row$time - to.merge$time[idx])]
df$val[i] <- to.merge$val[j]
}
}
(df
は〜12K行to.merge
が持っている〜250kの行を持っている)作品
一つの方法は、forループであるが、それは私のデータのためにはるかに時間がかかりすぎます何とかのように、マージを行うことができます。
to.merge$closest_time_in_df <- sapply(to.merge$time,
function (tm) {
dts <- abs(tm - df$time)
# difference must be at most 1
if (min(dts) <= 1) {
df$time[which.min(dts)]
} else {
NA
}
})
merge(df, to.merge,
by.x=c('x', 'y', 'time'),
by.y=c('x', 'y', 'closest_time_in_df'),
all.x=T)
しかし、これは(2, 1, 11.5, c)
ためto.merge$closest_time_in_df
が12であるため、(2, 1, 11)
行をマージしますが、時間はありませんdf
の12は(x、y)=(2,5)ではないため、マージは失敗します。
' df'の時刻が6で、 'to.merge'の時刻が2で、1より大きいため、行9はそこにはありません。 –
@ mathematical.coffeeは答えを編集しました –
よかった!複数の 'merge'を使うと非常に巧妙です。私は決して' aggregate'を使用していませんe。また、 'all.x'は私が信じる最初の' merge'では必要ありません。 –