2016-06-30 4 views
2

У меня есть dataframe, который выглядит примерно так:R dplyr сцепления группы, в функцию

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 

Вы можете генерировать что-то подобное с помощью этого:

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) 

И функция для вычисления среднего времени между пиками в отфильтрованном сигнале (среднее среднее время и дисперсия разностей во времени):

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 шляпа я пытаюсь сделать применить эту функцию для каждой комбинации id, trialNum и trialType использованием groupby:

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

Проблема заключается в том, что в выходном dataframe (tempTrial) каждый ряд meanTime и varianceTime идентичен

в этом игрушечном наборе данных, иногда столбцы все показывают NA (это не случается в моем фактическом наборе данных)

Я делаю что-то неправильно, чтобы вызвать каждую строку, чтобы быть я зубной для 2 столбцов? Следует принимать каждую комбинацию id, trialNum и trialType и рассчитывать время пиков для каждого из них отдельно. Однако кажется, что он сохраняет только одно значение для каждой комбинации?

+0

Я получаю сообщение об ошибке. 'Ошибка: не удалось найти функцию« масло ». Пожалуйста, укажите имена библиотек. – user2100721

+0

добавлено - см. Править – Simon

+0

Здесь 'findPeaks (отфильтровано)' возвращающ 'числовое (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.Просто замените ваш summarise с do:

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

Документация do не очень понятно, но this post описывает применение очень хорошо.

1

Как отметил сам и Латрунчулия, calcStepTime, скорее всего, вернет NaN/NA в 50 наборов данных наблюдений. Это происходит, когда в группе наблюдений не обнаружено ни пика, ни одного пика. Вы можете защитить от этого в своем аналитическом коде. Я использовал это для тестирования:

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 (Тиббл), например так:

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, возвращаемом вашей функцией.

Смежные вопросы