2014-02-18 38 views
1

我希望我能做一個令人滿意的解釋我的問題的工作。我可以讓R做我想做的事,但感覺非常笨拙,所以我正在尋找更好的方法來達到同樣的結果。將邏輯應用於R中的數據幀列

我有一個看起來是這樣的一個數據幀(雖然我也開放給其他的結構,如果他們更好地工作。)

subject <- c(1,1,3,3) 
day  <- c(3, 20, 1, 14) 
status <- c(1, 1, 1, 3) 
df  <- cbind(subject, day, status) 

我想找到最有效的方式來見,例如,如果主體1在第3天具有狀態1(是)或者在第20天測試主體具有除3以外的任何狀態。到目前爲止,我的嘗試是功能性的,但笨拙和醜陋。

has_event <- function(i, j, data) { 
    any(data[(data[, "subject"] == i) & (data[, "status"] != 3), "day"] == j) 
} 

has_event(1, 3, df) # evaluates to TRUE 
has_event(1, 4, df) # evaluates to FALSE 

我沒有看到這個方法走得很遠,因爲邏輯從這裏變得更加複雜。我覺得我錯過了一些調用數據的非常簡單的方法。如果我想看到很多科目沒怎麼有3個在特定日期中的狀態,例如,它看起來像這樣用我的方法:

length(unique(df[, "subject"],)) - length(which(df[, "status"] == 3 & df[, "day"] == 14)) 

而這僅僅是無法控制的。

總體目標是以我可以按日期或按主題輕鬆訪問事物的方式來格式化數據,但是我現在只是無法確定調查的途徑。

回答

3

dplyr::filter()怎麼樣,但記得要將您的矩陣轉換爲data.frame。只需逐個添加過濾條件即可。

df<-data.frame(df) 

require(dplyr) 

filter(df,status!=3,day==20) 

    subject day status 
1  1 20  1 

或用data.table

require(data.table) 

data.table(df)[status!=3][day==20] 

其實它的時序爲100個000區域經濟共同體dplyr速度較快,但都很快,這些各種各樣的簡單排序:

df<-data.frame(subject=sample(1:5,100000,T),day=sample(1:20,100000,T),status=sample(1:10,100000,T)) 

> system.time(data.table(df)[status!=3][day==20]) 
user system elapsed 
0.01 0.00 0.02 
> system.time(filter(df,status!=3,day==20)) 
user system elapsed 
0  0  0 
+0

看起來不錯。在我可以嘗試之前,我不得不更新我的R版本(這是不必要的複雜)。我對此一無所知,但是你會認爲這是一個合理快速的解決方案,用於運行大數據集(10000ish)的模擬? –

+0

是的,我認爲dplyr的性能非常好,可以與data.table相媲美 - 但如果您不想升級,我已經在上面包含了一個data.table示例。我認爲dplyr的語法更直觀一些,但是對於這個過濾data.table的例子也是非常簡單的。 – Troy

+0

我更新了R並檢查出來,並且將它標記爲已解決,因爲它對於我所需要的大部分內容來說都非常完美。我仍然有可笑的問題,但我認爲這是一個單獨的問題。我從來不知道事件歷史分析會需要這樣不必要的複雜數據設置!現在我明白爲什麼現場所有的生存包都需要預先準備好如此多的數據。謝謝! –

2

使用sqldf包:

df <- data.frame(df) 
require(sqldf) 

sqldf("select * from df where status!=3 and day=20") 

    subject day status 
1  1 20  1 
+0

我大多驚訝這是一件存在的事情。哇,這句話看起來不簡單嗎?我想我喜歡SQL。 –