我正試圖合并兩個不同大小的資料框架,但由于資料的面板結構,我遇到了困難。
請看下面的例子,'Toy.left'是一個由三個變陣列成的面板:一個坐標('坐標'),以及在特定月份('月份')分配給該坐標的一個名稱('名稱')。接下來,考慮'Toy.right',它由四個變陣列成:一個名字('name'),該名字在分配到該坐標的任期的開始('tenure.start'),以及他們在分配到該坐標的任期的結束('tenure.end')。
toy. left < - tribble(~month, ~coord, ~name,
"2000-01-01", 1301, "Alpha", ,
"2000-03-01", 1301, "Beta",
"2000-06-01", 1302。 "Charlie", "Charlie",
"2000-09-01", 1303。 "Delta", "Delta",
"2000-12-01", 1303。 "Epsilon")
玩具。 右< - tribble(~name。 ~coord, ~tenure. start, ~tenure.end,
"Alpha", 1301。 "2000-02-01", "2000-04-01", "2000-04-01",
"Beta", 1301。 "1999-11-01", "2000-04-01",
"Charlie", 1302。 "2000-04-01", "2000-07-01",
"Delta", 1303。 "2000-08-01", "2000-10-01",
"Epsilon", 1303。 "2000-11-01", "2001-01-01",
"Delta", 1303。 "2002-01-01", "2004-01-01")
我想合并這兩個資料集,但有一些規則使dplyr中的merge()難以實作。例如,我不能簡單地使用inner_join()并通過'name'和'coord'進行合并,因為這違反了資料的面板結構。如果我這樣做,個人的任期就不會與觀察的月份重疊(首先,請看第1&2行,這應該是倒置的;其次,請看第4&5行,其中merge()重復了月份觀察,但應該只包括第4行)。
toy.left %>%
inner_join(toy. right, by = c("name", "坐標"))
*Output*
月度坐標名稱 tenure.start tenure.end
2000-01- 01 1301 Alpha 2000- 02-01 2000-04-01
2000- 03- 01 1301 Beta 1999- 11-01 2000-04-01
2000- 06- 01 1302 Charlie 2000- 04-01 2000-07-01
2000-09- 01 1303 Delta 2000- 08-01 2000-10-01
2000-09- 01 1303 Delta 2002- 01-01 2004-01-01
2000- 12- 01 1303 Epsilon 2000- 11-01 2001-01-01
為了解決這個問題,我可以通過 "姓名"、"坐標"、和"月份 "來合并資料,但是我需要根據日期是否在 "任期開始 "和 "任期結束 "之間來確定 "月份 "的合并條件。經過搜索,我無法找到一種方法來將自定義規則應用于 dplyr 中的 merge() 。
我知道自定義函式或回圈可能是處理這個問題的最佳方式,但我不確定從哪里開始。此外,原始資料集有超過150萬個觀察值,這可能會產生進一步的問題。
我歡迎你的建議!
uj5u.com熱心網友回復:
(所有這些都是在將month和tenure.*轉換為Date類之后。)
fuzzyjoin
。fuzzyjoin::fuzzy_inner_join()
toy.left, toy.right,
by=c("name"。 "坐標",月份="任期。 start", month="tenure.end"),
match_fun=list(`==`,`=`, `> =`, `<=`))
# # A tibble: 4 x 7
# month coord.x name.x name.y coord.y tenure.start tenure.end
# <date> <dbl> <chr> <chr> <dbl> <date>
# 1 2000-03-01 1301 Beta Beta 1301 1999-11-01 2000-04-01。
# 2 2000-06-01 1302 Charlie Charlie 1302 2000-04-01 2000-07-01
# 3 2000-09-01 1303 Delta Delta 1303 2000-08-01 2000-10-01[/span
# 4 2000-12-01 1303 Epsilon Epsilon 1303 2000-11-01 2001-01-01[/span
sqldf
sqldf::sqldf()
"select tl.name, tl.coord, tl.month, tr. [tenure.start], tr. [tenure.end]
from [Toy.left] tl
inner join [Toy.right] tr on tl.name=tr.name and tl.coord=tr.coord
和tl.month在tr.[tenure.start]和tr.[tenure.end]之間")。
# name coord month tenure.start tenure.end
# 1 Beta 1301 2000-03-01 1999-11-01 2000-04-01。
# 2 Charlie 1302 2000-06-01 2000-04-01 2000-07-01[/span
# 3 Delta 1303 2000-09-01 2000-08-01 2000-10-01[/span]。
# 4 Epsilon 1303 2000-12-01 2000-11-01 2001-01-01[/span
(我使用[tenure.start]與括號說明來區分表的識別符號tl和列名tenure.start,在SQL中,列名中的點通常表示schema.tablename.columnname類似命名。)
data.table
。這是做左鍵連接,而不是其他型別。為了確定哪些是由于做左接而不是內接而應該被洗掉的,我將在toy.left中添加一列:
library(data.table)
setDT(toy.left)
setDT(toy.right)
toy.left[, val := 2]
toy.left[toy.right, on = . (name, coord, month >= tenure。 start, month <= tenure. end)][ ! is. na(val),]/span>
# month coord name val month.1
# <Date> <num> <char> <num> <Date>
# 1: 1999-11-01 1301 Beta 2 2000-04-01
# 2: 2000-04-01 1302 Charlie 2 2000-07-01。
# 3: 2000-08-01 1303 Delta 2 2000-10-01。
# 4: 2000-11-01 1303 Epsilon 2 2001-01-01。
data.table有它重命名列的方式,所以要注意它。當我不確定我是否知道最終的命名方式時,我經常會把列復制過來,這樣就會很清楚......但我這樣做的部分原因是懶得去了解它到底是如何確定結果名稱的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/326654.html
標籤:
