2016-07-23 15 views
1

IDと曜日の列を含む2つのデータフレームxとyがあります。 Iは、ID及び天気をdate.yを照合することによって、新しいデータフレームのZにそれらを結合したいIDと重複する日付範囲でデータフレームを結合する

id.x <- c(1, 2, 4, 5, 7, 8, 10) 
date.x <- as.Date(c("2015-01-01", "2015-01-02", "2015-01-21", "2015-01-13", "2015-01-29", "2015-01-01", "2015-01-03"),format = "%Y-%m-%d") 
x <- data.frame(id.x, date.x) 
id.y <- c(1, 2, 3, 6, 7, 8, 9) 
date.y <- as.Date(c("2015-01-03", "2015-01-29", "2015-01-22", "2015-01-13", "2015-01-29", "2014-12-31", "2015-01-03"), format = "%Y-%m-%d") 
y <- data.frame(id.y, date.y) 

は、例えば、3 + date.x日以内に発生しましたDate.x = "2015-01-01"のイベントxの3日以内にdate.y = "2015-01-03"にイベント "y"が発生しました。

+0

data.framesを作成するために 'cbind'を使用しないでください。ちょうどそのために利用できるdata.frame関数があります。 – Arun

+0

@Arun注目。他の誰かが 'cbind.data.frame()'と 'data.frame()'の違いについて興味を持たれていれば、ここでうまくまとめられています(https://docs.tibco.com/pub/enterprise-runtime- 'の行動を取得する('/1.5.0_may_2013/TERR_1.5.0_LanguageRef /ベース/ cbind.data.frame.html R-用) – user6571411

+0

使用 'check.names(data.frame'へのコールに= false'に) cbind.data.frame')、唯一のデフォルトの違いと思われる。 – Arun

答えて

1

date.y < = date.x + 3とdate.y> = date.xの場合はdate.xと等しく、それ以外の場合はdate.yと等しいベクトルを作成するifelse文を作成できます。そして、このベクトルに基づいて2つをマージ:

id.x <- c(1, 2, 4, 5, 7, 8, 10) 
date.x <- as.Date(c("2015-01-01", "2015-01-02", "2015-01-21", "2015-01-13", "2015-01-29", "2015-01-01", "2015-01-03"),format = "%Y-%m-%d") 
x <- cbind.data.frame(id.x, date.x) 
id.y <- c(1, 2, 3, 6, 7, 8, 9) 
date.y <- as.Date(c("2015-01-03", "2015-01-29", "2015-01-22", "2015-01-13", "2015-01-29", "2014-12-31", "2015-01-03"), format = "%Y-%m-%d") 
y <- cbind.data.frame(id.y, date.y) 

safe.ifelse <- function(cond, yes, no) structure(ifelse(cond, yes, no), class = class(yes)) 

match <- safe.ifelse(date.y <= date.x+3 & date.y >= date.x, 
      match <- date.x, 
      match <- date.y) 

y$date.x <- match 
names(y)[1] <- "id.x" 

dplyr::left_join(x, y, by=c("id.x","date.x")) 

    id.x  date.x  date.y 
1 1 2015-01-01 2015-01-03 
2 2 2015-01-02  <NA> 
3 4 2015-01-21  <NA> 
4 5 2015-01-13  <NA> 
5 7 2015-01-29 2015-01-29 
6 8 2015-01-01  <NA> 
7 10 2015-01-03  <NA> 

私は数値ベクトルではなく、日付ベクトルのベースifelse文の結果ので、このpostからsafe.ifelse機能を借りました。

+0

これは安全ではなく、一般的に間違った解決策につながります。あなたの世代の 'match'カラムは' id'カラムを全く考慮しません。 – Arun

+0

私はArunが言及する問題に遭遇しました。私の回避策は次の通りです 'temp < - merge(x、y、by.x =" id.x "、by.y =" id.y "、すべて=真)' 'temp.subset < - safe.ifelse(date.y <= date.x + 3&date.y> = date.x、TRUE、FALSE) ' 'joined.df < - TEMP [(temp.subset == TRUE)] ' – user6571411

1

両方のデータテーブルのidにキーを設定し、日付条件をチェックし、最後に真のデータを抽出することで、yとxデータテーブルの内部結合を使用します。 非エクイ(または条件)

v1.9.7、data.tableの開発バージョンを使用して
library("data.table") 

x <- as.data.table(x) 

y <- as.data.table(y) 

setkey(x, id.x) 

setkey(y, id.y) 

z <- y[x, nomatch = 0][, j = .(is_true = ((date.y <= date.x + 3) & (date.y > date.x)), id.y, date.x, date.y)][i = is_true == TRUE] 

> z 
    is_true id.y  date.x  date.y 
1: TRUE 1 2015-01-01 2015-01-03 
1

は、最近実施された結合は、我々は簡単(かつ効率的)な方法でこれを行うことができます。..インストール手順を参照してください。 here

次いで
require(data.table) # v1.9.7+ 
setDT(x) 
setDT(y) ## convert both data.frames to data.tables by reference 

x[, date.x.plus3 := date.x + 3L] 
y[x, .(id.x, date.x, date.y=x.date.y), 
    on=.(id.y == id.x, date.y >= date.x, date.y <= date.x.plus3)] 
# id.x  date.x  date.y 
# 1: 1 2015-01-01 2015-01-03 
# 2: 2 2015-01-02  <NA> 
# 3: 4 2015-01-21  <NA> 
# 4: 5 2015-01-13  <NA> 
# 5: 7 2015-01-29 2015-01-29 
# 6: 8 2015-01-01  <NA> 
# 7: 10 2015-01-03  <NA> 

ダミー列に参加ソリューションおよび条件に基づいてフィルタリングする(行の数が急速に爆発するように)、一般にスケーラブルではないにし、行をループソリューションと行ごとにフィルタ条件を実行しています遅いです。なぜなら、彼らは行単位で操作を実行するからです。

このソリューションはどちらも、即ち、条件が直接結合を実行しないので、両方のランタイムとメモリの点でパフォーマンスでなければなりません。

関連する問題