2015-10-07 3 views
3

У меня есть образец dataframe, что я работаю сРасчет интенсивности отказов и времени манипуляции даты в R

Datetime <- c("2015-09-29 08:22:00", "2015-09-29 09:45:00", "2015-09-29 09:53:00", "2015-09-29 10:22:00", "2015-09-29 10:42:00", 
        "2015-09-29 11:31:00", "2015-09-29 11:47:00", "2015-09-29 12:45:00", "2015-09-29 13:11:00", "2015-09-29 13:44:00", 
        "2015-09-29 15:24:00", "2015-09-29 16:28:00", "2015-09-29 20:22:00", "2015-09-29 21:38:00", "2015-09-29 23:34:00") 
Measurement <- c("Length","Length","Width","Height","Width","Height","Length","Width","Width","Height","Width","Length", 
        "Length","Height","Height") 
PASSFAIL <- c("PASS","PASS","FAIL","PASS","PASS","FAIL_AVG_HIGH","FAIL#Pts","FAIL","FAIL_AVG_LOW","FAIL","PASS","PASS","FAIL#RNG#HIGH","PASS","FAIL") 

df1 <- data.frame(Datetime,Measurement,PASSFAIL) 

df1

   Datetime Measurement  PASSFAIL 
1 2015-09-29 08:22:00  Length   PASS 
2 2015-09-29 09:45:00  Length   PASS 
3 2015-09-29 09:53:00  Width   FAIL 
4 2015-09-29 10:22:00  Height   PASS 
5 2015-09-29 10:42:00  Width   PASS 
6 2015-09-29 11:31:00  Height FAIL_AVG_HIGH 
7 2015-09-29 11:47:00  Length  FAIL#Pts 
8 2015-09-29 12:45:00  Width   FAIL 
9 2015-09-29 13:11:00  Width FAIL_AVG_LOW 
10 2015-09-29 13:44:00  Height   FAIL 
11 2015-09-29 15:24:00  Width   PASS 
12 2015-09-29 16:28:00  Length   PASS 
13 2015-09-29 20:22:00  Length FAIL#RNG#HIGH 
14 2015-09-29 21:38:00  Height   PASS 
15 2015-09-29 23:34:00  Height   FAIL 

Я работаю на интересной проблеме, чтобы найти частоту отказов для каждого измерения в 12 AM-12PM & 12 PM-12AM (на следующий день) в день.

Примечание: В df1 все, что имеет FAIL в столбце PASSFAIL, считается сбоем.

Fail Rate = (Number of Fails)/(Number of Fails + Number of Pass) 

Мой желаемый результат что-то вроде этого

   Datetime FailRate_length Total_length FailRate_Width Total_Width FailRate_Height Total_Height 
1 2015-09-29 00:00:00 AM   0.33   3   0.50   2   0.50   2 
2 2015-09-29 12:00:00 PM   0.50   2   0.66   3   0.66   3 

Я пытаюсь использовать dplyr и data.table пакеты для решения этой проблемы, но я просто не зная, как разделить временные интервалы в df1 для получаем df2, который имеет 2 значения -> 12AM (первые 7 наблюдений df1) & 12PM (Следующие 8 наблюдений в df1). Может ли кто-нибудь помочь мне в этом?

ответ

5

Использование data.table ...

library(data.table) 

# thanks to @DavidArenburg for suggesting this approach: 

df1[, `:=`( 
    d  = as.IDate(Datetime), 
    antepost = c("am","pm")[1+(hour(Datetime) >= 12)]) 
] 

res <- setDT(df1)[ , .( 
    failrate = sum(PASSFAIL != "PASS")/.N, 
    N   = .N 
), by = .(d, antepost, Measurement)] 

который дает

  d antepost Measurement failrate N 
1: 2015-09-29  am  Length 0.3333333 3 
2: 2015-09-29  am  Width 0.5000000 2 
3: 2015-09-29  am  Height 0.5000000 2 
4: 2015-09-29  pm  Width 0.6666667 3 
5: 2015-09-29  pm  Height 0.6666667 3 
6: 2015-09-29  pm  Length 0.5000000 2 

Синтаксис является DT[i,j,by] где by для группировки переменных; и j - для работы с колонками. := в пределах j создает новые столбцы.

Чтобы изменить форму до нужного выхода операционного в ...

dcast(res, d + antepost ~ Measurement, value.var = c("failrate", "N")) 

который дает

  d antepost failrate_Height failrate_Length failrate_Width N_Height N_Length N_Width 
1: 2015-09-29  am  0.5000000  0.3333333  0.5000000  2  3  2 
2: 2015-09-29  pm  0.6666667  0.5000000  0.6666667  3  2  3 

Благодаря @Arun, вот способ сделать все это за один шаг:

dcast(setDT(df1), 
    as.IDate(Datetime) + c("am","pm")[1+(hour(Datetime) >= 12)] ~ Measurement, 
    value.var = "PASSFAIL", 
    fun.agg = list(function(x) sum(x != "PASS")/length(x), length) 
) 

, который дает

 Datetime Datetime_1 PASSFAIL_function_Height PASSFAIL_function_Length PASSFAIL_function_Width PASSFAIL_length_Height PASSFAIL_length_Length PASSFAIL_length_Width 
1: 2015-09-29   am    0.5000000    0.3333333    0.5000000      2      3      2 
2: 2015-09-29   pm    0.6666667    0.5000000    0.6666667      3      2      3 

Имена столбцов автоматически генерируется из корневых переменных в ~ части и первое слово каждого определения функции.

+0

Я получил первую часть скрипт работает. Это выглядит замечательно. Но линия dcast выдает ошибку: «Ошибка в .subset2 (x, i, exact = exact): индекс за пределами границ». Не могли бы вы проверить это? – Sharath

+2

Очень приятно, хотя, вероятно, более эффективно создавать 'd' и' antepost' перед операциями группировки, если набор данных очень велик, поскольку 'as.IDate' и' as.POSIXlt' не очень эффективны. –

+2

@Sharath Возможно, у вас нет последней версии пакета data.table ...? Он работает на моем конце. Возможно, начните новую сессию R только для проверки этого кода и сравните 'sessionInfo()' с последней версией data.table на CRAN (в настоящее время 1.9.6) – Frank

3

dplyr + tidyr эквивалентно (с несколько иной биннинга, хотя выше один элегантна):

library(plyr) 
library(dplyr) 
library(tidyr) 

df1 %>% 
    mutate(
    half_day = 
     Datetime %>% 
     as.POSIXct(tz = "UTC") %>% 
     round_any(60*60*12, f = floor)) %>% 
    group_by(half_day, Measurement) %>% 
    summarize(Total = n(), 
     FailRate = sum(PASSFAIL != "PASS")/Total) %>% 
    gather(variable, value, FailRate, Total) %>% 
    unite(variable_new, variable, Measurement, sep = "_") %>% 
    spread(variable_new, value) 

gather, unite, spread последовательность представляет собой tidyr эквивалент dcast.Обратите внимание, что

половина дня * (12 час/полдня) * (60 мин/час) * (60 секунд/мин) = 60 * 60 * 12 секунд

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