2016-06-30 20 views
2

Ich habe einen Datenrahmen, die etwa wie folgt aussieht:R dplyr Gruppe verketten, indem sie in Funktion

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 

Sie etwas ähnliches mit diesem erzeugen kann:

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) 

Und eine Funktion, um die durchschnittliche Zeit zu berechnen zwischen Spitzen in einem gefilterten Signal (mittlere Antwortzeit und Varianz der Zeitdifferenzen):

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 Hut Ich versuche, diese Funktion zu jeder Kombination von id zu tun gelten, trialNum und trialType mit groupby:

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

Das Problem ist, dass in dem Ausgangsdatenrahmen (tempTrial) jede Reihe von meanTime und varianceTime identisch ist

in diesem Spielzeug-Datensatz, manchmal die alle Spalten zeigen NA (dies nicht in meinem aktuellen Datensatz geschehen)

Mache ich etwas falsch jede Zeile zu verursachen i zu sein Zahn für die 2 Säulen? Es sollte jede Kombination von id, trialNum und trialType genommen werden, und Berechnung der Spitzenzeiten für jede von denen separat. Es scheint jedoch nur einen einzigen Wert für jede Kombination zu speichern.

+0

Ich erhalte einen Fehler. 'Fehler: konnte die Funktion" butter "nicht finden' Bitte geben Sie die Bibliotheksnamen an. – user2100721

+0

hinzugefügt - siehe Bearbeiten – Simon

+0

Hier, 'findPeaks (gefiltert)' zurückgeben 'numerisch (0)' – user2100721

Antwort

1

Was Sie jetzt bekommen, ist das Ergebnis von calcStepTime angewendet auf den gesamten (ungruppierten) Datenrahmen für jede Gruppe.

Versuchen Sie, die Funktion so umzuschreiben, dass sie von den Variablen abhängt, nicht jedoch vom Datenrahmen.

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]) 

Es gibt das richtige Ergebnis, wenn Sie nur den testDF-Datenrahmen hineinleiten. Es bricht für den gruppierten DF, aber ich kann nicht finden, ob das, weil die Funktion für die Teilmengen nicht definiert ist oder wenn es ein Problem mit der Funktion ist.

lassen Sie mich wissen, ob es für die vollständigen Daten

2

Die Kette funktioniert einwandfrei in dem Sinne, dass . bezieht sich auf die gruppierte Datenrahmen group_by(testDF, id, trialNum, trialType) funktioniert. Da Ihre definierte Funktion keine Möglichkeit hat, die Gruppeninformation in . zu verwenden, sind die Ergebnisse das, was Sie sehen (d. H. Die auf den gesamten Datenrahmen angewendete Funktion).

Ihr Problem hier ist also die falsche Verwendung von summarise. Die Antwort von Latrunculia zeigt Ihnen, dass Sie die Funktion summarise in der von Ihnen erwarteten Weise verwenden sollten, indem Sie die Funktion auf Spaltenkombinationen in Ihrem Datenrahmen anwenden. In diesem Fall wird die Funktion in jeder Variablen nach Gruppen angewendet.

dplyr hat eine do Funktion für Anwendungen, bei denen Sie möchten eine Funktion für die Datenrahmen Teilmenge von group_by implizierten anzuwenden.Ersetzen Sie einfach Ihre summarise mit do:

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

Die Dokumentation für do nicht sehr klar, aber this post beschreibt die Anwendung sehr gut.

1

Wie von Ihnen selbst und Latrunculia festgestellt, ist es sehr wahrscheinlich, dass calcStepTime NaN/NA auf den 50 Beobachtungsdatensätzen zurückgibt. Dies tritt auf, wenn innerhalb einer Gruppe von Beobachtungen entweder kein Peak oder ein einzelner Peak gefunden wurde. Sie können sich in Ihrem Analysecode dagegen wehren. Ich habe dies für die Prüfung:

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) 

Wenn Sie den Rückgabetyp Ihrer Funktion von data_frame (tibble) ändern, etwa so:

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)) 
} 

Dann können Sie die Vorteile von purrr::by_slice() für eine ziemlich elegante Lösung nehmen :

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

ich habe dies aus meiner Testprobe:

# 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 

Beachten Sie, dass .collate="cols" das wichtige Argument ist, das by_slice() anweist, die benannten Spalten für die Ergebnisse in der Ausgabe zu erstellen. Ich bin ein wenig neugierig, warum die "1" an die Namen angehängt wurde, die wir in dem von Ihrer Funktion zurückgegebenen Datenrahmen gesetzt haben.