2014-01-15 26 views
1

我意識到這個主題有很多問題,但我無法通過查看各種答案來解決我的問題。我有一個DF - 的提取物,其中附加如下:按因子分解df,應用函數並返回合併的df

ID = as.factor(c("1","1","1","1","1", 
       "2","2","2", 
       "3","3","3","3", 
       "4","4","4","4","4")) 
AdDate = c("2010-03-04", "2010-04-05", "2011-01-23", "2011-03-20", "2012-07-08", 
      "2010-12-02", "2011-05-17", "2011-09-11", 
      "2010-04-11", "2010-05-15", "2011-02-22", "2011-09-23", 
      "2009-10-04", "2010-02-15", "2010-08-17", "2011-06-20", "2012-04-08") 
OpofInterest = c("FALSE", "FALSE", "TRUE", "FALSE", "FALSE", 
       "FALSE", "TRUE", "FALSE", 
       "FALSE", "FALSE", "TRUE", "FALSE", 
       "FALSE", "FALSE", "TRUE", "FALSE", "FALSE") 
df = data.frame(ID, AdDate, OpofInterest) 

什麼然後我想要做的是(在該實施例4)通過ID的DF分成多個dataframes的,然後應用下面的功能根據AdDate爲每個人(ID)分配其他情節(每行)是否在手術前(手術前),手術相同(每次手術)或手術後(手術後)。我是新來的R和編程,並在下面產生了一個功能。實際上,我有成千上萬的ID和劇集,以及大約80列,所以我不能單獨分組和應用我經過一些調整後才能工作的功能。

prepostassignment <- function (df) { 

df_OpofInterest = subset(df,(df["OpofInterest"] == "TRUE")) 

for (i in 1:nrow(df)) { 

if (df$AdDate[i] < df_OpofInterest$AdDate) { 
    df$Pre_Post_Assignment[i] = "Pre" 

} else if (df$AdDate[i] == df_OpofInterest$AdDate) { 
    df$Pre_Post_Assignment[i] = "Per" 

} else if (df$AdDate[i] > df_OpofInterest$AdDate) { 
    df$Pre_Post_Assignment[i] = "Post" 

    } 
} 
} 

我已經通過,tapply,骨料,ddply發揮四周,似乎無法拿出一個 解決方案。我使用的手動子集的功能時,也已經得到以下錯誤信息:

遺漏值,其中TRUE/FALSE需要

我已經在這個閱讀起來很好,但無法理解它是怎麼回事錯在我的特殊代碼

我想落得如下:

ID = as.factor(c("1","1","1","1","1", 
       "2","2","2", 
       "3","3","3","3", 
       "4","4","4","4","4")) 
AdDate = c("2010-03-04", "2010-04-05", "2011-01-23", "2011-03-20", "2012-07-08", 
      "2010-12-02", "2011-05-17", "2011-09-11", 
      "2010-04-11", "2010-05-15", "2011-02-22", "2011-09-23", 
      "2009-10-04", "2010-02-15", "2010-08-17", "2011-06-20", "2012-04-08") 
OpofInterest = c("FALSE", "FALSE", "TRUE", "FALSE", "FALSE", 
       "FALSE", "TRUE", "FALSE", 
       "FALSE", "FALSE", "TRUE", "FALSE", 
       "FALSE", "FALSE", "TRUE", "FALSE", "FALSE") 
Pre_Post_Assignment = c("Pre", "Pre", "Per", "Post", "Post", 
         "Pre", "Per", "Post", 
         "Pre", "Pre", "Per", "Post", 
         "Pre", "Pre", "Per", "Post", "Post") 
df_new = data.frame(ID, AdDate, OpofInterest, Pre_Post_Assignment) 

任何幫助將不勝感激。

謝謝。

+0

什麼是你的第二個代碼塊中的'df_OpofInterest'和'df_TAVI'? – josliber

+0

道歉,df_TAVI應該是df_OpofInterest。爲了獲得在函數 – sgurwin

+0

中使用的AdDate,我爲子集「利益操作」進行了子集。爲什麼您要從類「字符」的列開始(然後轉換爲「因子」)?不應該是'整數',日期是'日期',OpofInterest是'邏輯'? –

回答

3

這是傳統的拆分應用聯合分析。下面是使用data.table一個選項:

df = data.frame(ID, AdDate, OpofInterest, stringsAsFactors=FALSE) 
df$OpofInterest <- as.logical(df$OpofInterest) 
library(data.table) 
dt <- data.table(df) 
dt[, 
    cbind(
    .SD, 
    Pre_Post_Assignment= 
     ifelse(
     AdDate < AdDate[OpofInterest], 
     "Pre", 
     ifelse(AdDate == AdDate[OpofInterest], "Per", "Post" 
    ))), 
    by=ID] 
#  ID  AdDate OpofInterest Pre_Post_Assignment 
# 1: 1 2010-03-04  FALSE     Pre 
# 2: 1 2010-04-05  FALSE     Pre 
# 3: 1 2011-01-23   TRUE     Per 
# 4: 1 2011-03-20  FALSE    Post 
# 5: 1 2012-07-08  FALSE    Post 
# 6: 2 2010-12-02  FALSE     Pre 
# 7: 2 2011-05-17   TRUE     Per 
# 8: 2 2011-09-11  FALSE    Post 
# 9: 3 2010-04-11  FALSE     Pre 
# 10: 3 2010-05-15  FALSE     Pre 
# 11: 3 2011-02-22   TRUE     Per 
# 12: 3 2011-09-23  FALSE    Post 
# 13: 4 2009-10-04  FALSE     Pre 
# 14: 4 2010-02-15  FALSE     Pre 
# 15: 4 2010-08-17   TRUE     Per 
# 16: 4 2011-06-20  FALSE    Post 
# 17: 4 2012-04-08  FALSE    Post 

您還可以使用ddply這一點。實際計算的肉是兩個嵌套的ifelse陳述。 [.data.table的第二個參數是除了split/grouping columnn(此處爲ID)之外的輸出中我們想要的列的列表。 .SD變量是一個特殊的data.table變量,它包含組中所有未在by參數中引用的列(這裏將包含AdDateOpofInterest)。我們cbind我們的另外的向量到.SD用額外的列創建我們的新結果。

其他幾個值得注意的地方:

  1. 我轉換日期字符串的比較工作
  2. 我轉換OpofInterest邏輯

最後,免責聲明,而分析的類型在這裏執行的是split-apply-combine,data.table的幕後實現不會分裂,而是應用,而是它的子集和迭代(我在這裏注意到這一點,所以Arun不會生我的氣)。


編輯:這裏是@ BlueMagister的建議:

dt[, 
    Pre_Post_Assignment:= 
    ifelse(
     AdDate < AdDate[OpofInterest], 
     "Pre", 
     ifelse(AdDate == AdDate[OpofInterest], "Per", "Post") 
    ), 
    by=ID 
] 

我認爲這是更清潔,最有可能的也更快。

+0

感謝您的幫助和建議,我明白這一點。例如,當你有80列以上的時候,你會建議幹什麼,在你的代碼的'list(cols ... = ifelse'部分?列名的命名向量? – sgurwin

+0

@sgurwin,我修改瞭解決你的問題的答案。請看'.SD'的東西 – BrodieG

+0

在'.SD'上定義一個新列比'cbind'更好,不是嗎? –