2016-09-22 54 views
1

我想編寫一個函數,根據唯一值[id]子組內的所有其他記錄,對數據集中的每條記錄執行操作。我很新的R,但我知道,您可以根據使用下面的條件查詢的記錄的子集:尋找有效的方式來查詢R或Stata中的子組觀察

df$date[id == "1234"] 

是否有可能取代「1234」從唯一的行衍生變量該功能正在運行?像...

df$date[id == df$id] 

,這樣它拉[index]行索引行[id]匹配[id]的[日期]的值。在實踐中我會在一個循環,其中對x的值,我用可以查詢特定[日期]值使用此:

df$date[id == df$id & order == x] 

我的數據集必須爲每個獨特的[ID]多個記錄。最終,我想將每個記錄的[date_1]值與每個索引記錄[id]子組中所有其他記錄的[date_2]進行比較。數據看起來是這樣的:

[id] | [order] | [date_1] | [date_2] | 
-------------------------------------- 
    A | 1 | 1/1 | 1/30 | 
    A | 2 | 1/5 | 1/5 | 
    A | 3 | 1/7 | 1/8 | 
    A | 4 | 1/9 | 1/9 | 
------------------------------------- 
    B | 1 | 3/7 | 3/10 | 
    B | 2 | 4/1 | 4/9 | 
-------------------------------------- 

雖然這可以通過每個唯一值[ID]循環,然後通過每個唯一值[爲了]循環來完成,記錄數(5-10萬)證明該方法極其緩慢且資源密集。我想知道是否有一種更有效的方法來簡單地遍歷[order]值,然後同時計算每個記錄的這個操作。

正如我所說的,我是新來的R,所以我不是萬能的確定確切的語法,但我正在想象這樣的事情:

for x = 1/max(order){ 
    df$episode_start <- 1 if df$date_1 - df$date_2[id == df$id & order == x] > 1 
    } 

我可以提供更多的細節這個項目的總體目標是否有用。簡而言之,這些數據是醫院記錄,目標是確定開始一個新細分的記錄,該記錄被定義爲在入院後1天內沒有事先解除的相遇。數據變得棘手,因爲存在重疊的記錄(例如,如果病人是長期護理的住院病人,並且不得不去門診就診到急診室) - 在上面的例子中,A2和A3看起來像是基於先前記錄的出院日期[日期2]新的遭遇,但是A2,A3和A4都A1的跨度中發生的,所以結果應該是這樣的:

[id] | [order] | [date_1] | [date_2] | [episode_start] 
------------------------------------------------------ 
    A | 1 | 1/1 | 1/30 |  1 
    A | 2 | 1/5 | 1/5 |  0 
    A | 3 | 1/7 | 1/8 |  0 
    A | 4 | 1/9 | 1/9 |  0 
----------------------------------------------------- 
    B | 1 | 3/7 | 3/10 |  1 
    B | 2 | 4/1 | 4/9 |  1 
------------------------------------------------------ 

在此先感謝。任何幫助或方向非常感謝。注意:我主要在Stata工作,並試圖使用-bysort-命令來做類似的事情,但無濟於事。也許以爲R更適合這個。使用任一方式打開建議。

+1

如果你要問的Stata過,這是樂觀的假設,人們將閱讀一個長期以R爲中心的問題,然後翻譯。有兩個人都很流利,但你在這方面的成功機率很低。我建議刪除Stata標籤,並提一提Stata提出的單獨Stata問題,如果您同時尋求Stata建議。當然,我不反對R的問題,但無法解決這個問題。 –

回答

0

這裏是什麼讓你開始R中使用data.table包:

data <- read.table(text = "id order date_1 date_2 
A 1 2016-01-01 2016-01-30 
A 2 2016-01-05 2016-01-05 
A 3 2016-01-07 2016-01-08 
A 4 2016-01-09 2016-01-09 
B 1 2016-03-07 2016-03-10 
B 2 2016-04-01 2016-04-9", header = T) 
library(data.table) 
data$date_1 <- as.Date(data$date_1) 
data$date_2 <- as.Date(data$date_2) 
dt <- data.table(data, key = c("date_1", "date_2")) 

res <- foverlaps(dt, dt, by.x = c("date_1", "date_2"), by.y = c("date_1", "date_2")) 

# Remove matches from irrelevant groups. 
res <- res[id == i.id] 

# Find the period start date. 
res[, min.date := min(i.date_1), by = .(id, order)] 
res[, period.start := (date_1 == min.date)] 

# Order records according to the period start date. 
res <- res[order(id, order, i.date_1)] 
# Remove duplicate rows 
res <- res[, .SD[1], by = .(id, order)] 

# Print resutls. 
res[, .(id, order, date_1, date_2, period.start)][] 

#  id order  date_1  date_2 period.start 
# 1: A  1 2016-01-01 2016-01-30   TRUE 
# 2: A  2 2016-01-05 2016-01-05  FALSE 
# 3: A  3 2016-01-07 2016-01-08  FALSE 
# 4: A  4 2016-01-09 2016-01-09  FALSE 
# 5: B  1 2016-03-07 2016-03-10   TRUE 
# 6: B  2 2016-04-01 2016-04-09   TRUE 
+1

太棒了! - 這看起來完全符合我的需要。我需要花一些時間來熟悉foverlaps(),但是謝謝你指點我。 – d4v1dn

+0

歡迎您! – Bulat

-1

我會使用dplyr包解決這個問題,這是一個可以通過運行install.packages('dplyr')然後library('dplyr')來安裝的幻想數據處理工具。

此軟件包的cheatsheet文件說明如何非常雄辯地處理數據:https://www.rstudio.com/wp-content/uploads/2015/02/data-wrangling-cheatsheet.pdf

我不能完全確定要計算什麼。你是否試圖根據每行中的值創建一個新的列?或者,你是否想要計算每個獨特的值ID?在前一種情況下,我會使用​​。在後一種情況下,我會使用group_by(id),然後像filter()summarise()這樣的函數爲每個ID生成一行新的數據幀。

0

一個方便的方式來獲得的子集進行處理是使用by。這會自動將您的data.frame(在這種情況下,通過ID)子集並允許您專注於處理每個ID的記錄。

result <- by(df, df$id, function(x){ 
       ## identify start dates for sub-group 
      }) 

但是,我懷疑你仍然會發現速度很慢。按照另一個答案中的建議使用data.table應該有助於解決這個問題。

您可以通過在ID組上並行處理來進一步加快處理速度。請參閱foreach包以獲取幫助。它可以讓你寫這樣的代碼(假設DF $ ID是一個因素):

foreach(i = levels(df$id)) %dopar% { 
    ## Identify start dates for group i 
} 
1

重疊住院的問題,從時間最多可顯示時間Statalist。看一個例子here。解決方案是將入場/出場日期二元組轉換爲長格式,並按時間順序排列這兩個事件。新的醫院咒語或者是對患者的第一次觀察,或者是在前一次觀察結束的時候患者出院。下面是與布拉特的R染料溶液得出的數據爲例(修改,添加2個額外的住宿):

* Example generated by -dataex-. To install: ssc install dataex 
clear 
input str1 id byte order str10(date_1 date_2) 
"A" 1 "2016-01-01" "2016-01-30" 
"A" 2 "2016-01-05" "2016-01-05" 
"A" 3 "2016-01-07" "2016-01-08" 
"A" 4 "2016-01-09" "2016-01-09" 
"A" 5 "2016-02-09" "2016-02-09" 
"B" 1 "2016-03-07" "2016-03-10" 
"B" 2 "2016-03-08" "2016-03-08" 
"B" 3 "2016-04-01" "2016-04-9" 
end 

gen ndate1 = date(date_1,"YMD") 
gen ndate2 = date(date_2,"YMD") 
format %td ndate1 ndate2 

* confirm that each observation is uniquely identified by 
isid id order, sort 

* reshape to long; event==1 => admission; event==2 => discharge 
reshape long ndate, i(id order) j(event) 

* push the discharge date a day later (to make consecutive stays overlap) 
replace ndate = ndate + 1 if event == 2 

* define an inout increment for admission and discharge events 
bysort id order (event): gen inout = cond(_n==1,1,-1) 

* for each patient, sort events by date; for multiple events on the same day, 
* put admissions before discharge 
gsort id ndate -event 
by id: gen eventsum = sum(inout) 

* if the previous eventsum is 0, a new hospitalization spell starts 
by id: gen spell = sum(_n == 1 | eventsum[_n-1] == 0) 

* return to the original wide form data 
keep if inout == 1 

* flag the first obs of each spell 
bysort id spell (ndate order): gen newspell = _n == 1 

list id order date_1 date_2 spell newspell, sepby(id spell) 

,結果:

. list id order date_1 date_2 spell newspell, sepby(id spell) 

    +---------------------------------------------------------+ 
    | id order  date_1  date_2 spell newspell | 
    |---------------------------------------------------------| 
    1. | A  1 2016-01-01 2016-01-30  1   1 | 
    2. | A  2 2016-01-05 2016-01-05  1   0 | 
    3. | A  3 2016-01-07 2016-01-08  1   0 | 
    4. | A  4 2016-01-09 2016-01-09  1   0 | 
    |---------------------------------------------------------| 
    5. | A  5 2016-02-09 2016-02-09  2   1 | 
    |---------------------------------------------------------| 
    6. | B  1 2016-03-07 2016-03-10  1   1 | 
    7. | B  2 2016-03-08 2016-03-08  1   0 | 
    |---------------------------------------------------------| 
    8. | B  3 2016-04-01 2016-04-9  2   1 | 
    +---------------------------------------------------------+ 
+0

感謝您在stata中提供一個很好的解決方案。我將支票交給了Bulat的R解決方案(因爲我將我的問題集中在R操作上),但實際上我最終將這個解決方案用於我的項目。 'eventsum'方法簡單,優雅,快捷。謝謝! – d4v1dn