2016-06-30 50 views
2

我有一個數據幀,看起來是這樣的:[R dplyr鏈組通過到功能

testDF <- data.frame(time = 1:50, 
        id = sample(1:10, size=50, replace=T), 
        trialNum = sample(1:15, size = 50, replace=T), 
        trialType = sample(c("none", "low", "high"), 
             size = 50, replace=T), 
        accX = sin(seq(1,50,1)), 
        gravX = 0.1) 

和一個函數來計算的平均時間:

time id trialNum trialType  accX  gravX 
1 1 6  7  low -0.38876217 10.185266 
2 2 1  6  low 0.68254705 10.741545 
3 3 3  15  high -0.21906854 9.466929 
4 4 2  15  none -0.03370001 9.490829 
5 5 4  1  high 0.16511542 10.986796 
6 6 9  2  none -0.10441621 9.915561 

您可以使用此產生類似的東西濾波信號中的峯值之間(返回平均時間和時差的方差):

library(dplyr) 
library(signal) 
library(quantmod) 

calcStepTime <- function(df){ 
    bf <- butter(1, c(0.03,0.05), type="pass") 
    filtered <- filtfilt(bf, df$accX - df$gravX) 

    peaks   <- findPeaks(filtered) 
    peakValue  <- filtered[peaks] 
    peakTime   <- df$time[peaks] 

    timeDifferences <- diff(peakTime) 
    meanStepTime  <- mean(timeDifferences) 
    varianceStepTime <- var(timeDifferences) 

    return(c(meanStepTime, varianceStepTime)) 
} 

W帽子,我試圖做此功能適用於idtrialNumtrialType每個組合使用groupby

tempTrial <- 
    group_by(testDF, id, trialNum, trialType) %>% 
    summarise(meanTime = calcStepTime(.)[1], 
       varianceTime= calcStepTime(.)[2]) 

的問題是,在輸出數據幀(tempTrial)的meanTimevarianceTime每一行與

在這個玩具的數據集,有時列都顯示NA(這並不在我的實際數據集中發生)

我做得不正確造成的每一行是我牙列的2列?應該採取id,trialNumtrialType的每個組合,並分別計算每個組合的峯值時間。但是,它似乎只存儲每個組合的單個值?

+0

我收到一個錯誤。 '錯誤:找不到函數「黃油」'請提供庫名稱。 – user2100721

+0

新增 - 請參閱編輯 – Simon

+0

在這裏,'findPeaks(filtered)'返回'numeric(0)' – user2100721

回答

1

你現在得到的結果是calcStepTime適用於整個(未分組)的數據框。

嘗試重寫函數,使其取決於變量,但不取決於數據幀。

alcStepTime <- function(var1, var2, var3){ 
    bf <- butter(1, c(0.03,0.05), type="pass") 
    filtered <- filtfilt(bf, var1 - var2) 

    peaks <- findPeaks(filtered) 
    peakValue <- filtered[peaks] 
    peakTime <- var3[peaks] 

    timeDifferences <- diff(peakTime) 

    meanStepTime <- mean(timeDifferences) 

    varianceStepTime <- var(timeDifferences) 

    return(c(meanStepTime, varianceStepTime)) 
} 



testDF %>% group_by(testDF, id, trialNum, trialType) %>% 
summarise(meanTime = calcStepTime(accX, gravX, time)[1], 
     varianceTime= calcStepTime(accX, gravX, time)[2]) 

它給出了正確的結果,如果你只是將testDF數據幀放入其中。它打破了分組的DF,但我找不到這是因爲函數沒有爲子集定義,或者如果它是函數的問題。

讓我知道它是否適合完整的數據

2

鏈在這個意義上,.指的是分組數據幀group_by(testDF, id, trialNum, trialType)正常工作。由於您定義的函數無法使用.中的組信息,因此結果就是您所看到的(即應用於整個數據幀的函數)。

所以你的問題在這裏是不正確的使用summarise。 Latrunculia的答案顯示,以期望的方式使用summarise的正確方法是將函數應用於數據框中列的組合,在這種情況下,該函數按組在每個變量中應用。

dplyr有一個do函數適用於您希望將函數應用於group_by所暗示的數據框子集的應用程序。只需更換您的summarisedo

tempTrial <- group_by(testDF, id, trialNum, trialType) %>% do(meanTime = calcStepTime(.)[1], varianceTime= calcStepTime(.)[2]) 

do的文檔並不十分清楚,但this post描述應用程序非常好。

1

正如您自己和Latrunculia所指出的,calcStepTime很可能會在50個觀測數據集上返回NaN/NA。這發生在一組觀察中未發現峯或單峯時。您可能想要在分析代碼中對此進行辯護。我用這個來進行測試:

testDF <- data.frame(time = 1:200, 
       id = sample(1:2, size=200, replace=T), 
       trialNum = sample(1:1, size = 200, replace=T), 
       trialType = sample(c("low"), size = 200, replace=T), 
       accX = sin(seq(1,200,1)), 
       gravX = 0.1) 

如果您改變的data_frame(tibble)函數的返回類型,就像這樣:

calcStepTime <- function(df){ 
    bf <- butter(1, c(0.03,0.05), type="pass") 
    filtered <- filtfilt(bf, df$accX - df$gravX) 

    peaks <- findPeaks(filtered) 
    peakValue <- filtered[peaks] 
    peakTime <- df$time[peaks] 

    timeDifferences <- diff(peakTime) 

    meanStepTime <- mean(timeDifferences) 

    varianceStepTime <- var(timeDifferences) 

    return (data_frame("meanStepTime" = meanStepTime, 
        "varianceStepTime" = varianceStepTime)) 
} 

然後你就可以利用purrr::by_slice()一個相當優雅的解決方案:

library(purrr) 
testDF %>% 
group_by(id, trialNum, trialType) %>% 
by_slice(calcStepTime, .collate="cols") 

我得到這個從我的測試樣品:

# A tibble: 2 x 5 
    id trialNum trialType meanStepTime1 varianceStepTime1 
    <int> <int> <fctr>   <dbl>    <dbl> 
1  1  1  low   42.75   802.2500 
2  2  1  low   39.75   616.9167 

請注意,.collate="cols"是告訴by_slice()爲輸出中的結果創建命名列的重要參數。我對自己有點好奇,爲什麼「1」被添加到我們在函數返回的data_frame中設置的名稱中。