2017-06-20 53 views
3

我想要的.SD功能與by =在非球菌結合加入:如何選擇指定列中每個組的前n行(加入後)?

data.table - select first n rows within group

.EACHI in data.table

示例數據:

tmp_dt1<- data.table(grp = c(1,2), time = c(0.2, 0.6, 0.4, 0.8, 0.25, 0.65)) 
tmp_dt2 <- data.table(grp = c(1,2), time_from = c(0.1, 0.5)) 
tmp_dt2 <- tmp_dt2[, time_to := time_from + 0.2] 

> tmp_dt1 
    grp time 
1: 1 0.20 
2: 2 0.60 
3: 1 0.40 
4: 2 0.80 
5: 1 0.25 
6: 2 0.65 
> tmp_dt2 
    grp time_from time_to 
1: 1  0.1  0.3 
2: 2  0.5  0.7 

現在,我需要的輸出是每個組中的第一次位於tmp_dt2中定義的範圍之間。我可以得到所有這樣的時代:

> tmp_dt1[tmp_dt2, .(grp, time = x.time, time_from, time_to), on = .(grp, time >= time_from, time <= time_to)] 
    grp time time_from time_to 
1: 1 0.20  0.1  0.3 
2: 1 0.25  0.1  0.3 
3: 2 0.60  0.5  0.7 
4: 2 0.65  0.5  0.7 

不過,我有一些麻煩,使用by提取每個grp第n行,沒有鏈接。舉個例子,當n = 1,所需的輸出是:

tmp_dt1[tmp_dt2, .(grp, time = x.time, time_from, time_to), 
     on = .(grp, time >= time_from, time <= time_to)][, .SD[1], by = grp] 

     grp time time_from time_to 
1: 1 0.2  0.1  0.3 
2: 2 0.6  0.5  0.7 

但是,這樣的:

> tmp_dt1[tmp_dt2, .(time = x.time[1], time_from[1], time_to[1]), on = .(grp, time >= time_from, time <= time_to), by = grp] 
Error in `[.data.table`(tmp_dt1, tmp_dt2, .(time = x.time[1], time_from[1], : 
    object 'time_from' not found 

不起作用。

使用,.SD接近,但給我結果的混亂結束在選擇的列的條款:

tmp_dt1[tmp_dt2, .SD[1], on = .(grp, time >= time_from, time <= time_to), by = grp] 
    grp time 
1: 1 0.2 
2: 2 0.6 

爲什麼我不想做一個鏈的原因是因爲memory issues。請注意,我只對data.table軟件包解決這個問題感興趣。

回答

2

你試過

tmp_dt1[tmp_dt2, on=.(grp, time>=time_from, time<=time_to), 
    x.time, by=.EACHI] # or head(x.time, 2L) to get first 2 rows etc. 

您需要自己重命名重複列,直到內部處理完成爲止,如here所述。

+1

謝謝你的回答,也是非常有用的鏈接,解釋'x.'符號 – Alex

2

一個選項是指定mult= first

tmp_dt1[tmp_dt2, .(grp, time = x.time, time_from, time_to), mult = "first", 
      on = .(grp, time >= time_from, time <= time_to)] 
# grp time time_from time_to 
#1: 1 0.2  0.1  0.3 
#2: 2 0.6  0.5  0.7 
+0

謝謝,「first n」呢? (編輯問題以消除第一行的重點) – Alex

+0

@Alex'mult'只有'first','last'和'all'選項。你可以查看[這裏](https://cran.r-project.org/web/packages/data.table/vignettes/datatable-keys-fast-subset.html)對於一般情況,你已經有了答案 – akrun

+0

謝謝,所以沒有辦法避免創建第一個大數據表,然後對它進行子集化? – Alex

1

如果你想減少內存使用另一種解決方案可能是更多的內存,即使它看起來很奇怪存儲臨時原來的鏈接方法有效導致一個變量(但它只包含兩列,每個組只包含前n行)並仍使用鏈接(但是在原始數據的較小子集上):

n = 1  # parameter: first "n" rows per group 
selected.rows <- tmp_dt1[tmp_dt2, .(rownum = .I[1:n]), on = .(grp, time >= time_from, time <= time_to), by = grp] 
tmp_dt1[selected.rows$rownum][tmp_dt2, .(grp, time = x.time, time_from, time_to), on = .(grp, time >= time_from, time <= time_to)] 

不是很優雅,也許慢(它複製的連接邏輯,並要求加入兩倍 - 即使在第二種情況下設置減少子)......

臨時結果集包含每個行號「匹配」,在原始數據表(使用data.table.I符號):

selected.rows 

    grp rownum 
1: 1  1 
2: 2  2 

這將是巨大的,該解決方案使用一個真正的大數據錶鏈比較...(如果我有更多的時間我會簡介這個)