2014-09-24 2 views
0

Мне нужно транспонировать df в R, а функция агрегации должна быть минимальной.R-reshape2 с функцией агрегации min

Пример:

library(reshape2) 
N <- 20 
df <- data.frame(rutcli=sample(101:103, N, replace=T), 
      mes_atras=sample(1:4, N, replace=T), pay_day=sample(1:30, N, replace=T)) 


s<-dcast(df, rutcli ~ mes_atras, fun.aggregate = min, value.var = 'pay_day') 
View(s) 

Но я получаю предупреждение:

предупреждение: В .fun (.value [0], ...): нет, не пропущенные аргументы в мин; возвращение Inf

И результаты не желаемая:

rutcli 1 2 3 4 
    101 1 1 Inf 1 
    102 Inf 2 14 8 
    103 3 6 2 25 

Как я могу решить эту проблему?

Благодаря

+0

Вы должны предоставить фактический фрейм данных (с 'dput') или установить случайное семя, чтобы сделать желаемые результаты воспроизводимыми. –

ответ

1

Вы получаете предупреждение, потому что вы просите минимальное значение пустого множества. Например, нет значений pay_day, для которых rutcli = 102 и mes_atras = 1, поэтому вместо этого возвращается Inf.

Вы можете увидеть это более легко, если вы установили fun.aggregate=length. Например:

library(reshape2) 
N <- 20 

set.seed(11) # To make the `sample` function reproducible 
df <- data.frame(rutcli=sample(101:103, N, replace=T), 
       mes_atras=sample(1:4, N, replace=T), 
       pay_day=sample(1:30, N, replace=T)) 

dcast(df, rutcli ~ mes_atras, fun.aggregate = length, value.var = 'pay_day') 

    rutcli 1 2 3 4 
1 101 4 4 2 0 
2 102 1 3 1 0 
3 103 2 2 0 1 

Нули представляют собой комбинации rutcli и mes_atras, для которых нет ни одного значения pay_day. Если мы запустим dcast на этом кадре данных с функцией min, мы получим Inf, где появляются нули:

dcast(df, rutcli ~ mes_atras, fun.aggregate = min, value.var = 'pay_day') 

    rutcli 1 2 3 4 
1 101 1 5 7 Inf 
2 102 18 13 14 Inf 
3 103 10 13 Inf 7 
Warning message: 
In .fun(.value[0], ...) : no non-missing arguments to min; returning Inf 

Вы можете получить NA вместо Inf с помощью одного из расщепленных применить-скомбинировать методы. @MatthewLundberg дает базовый метод R. Вот один с dplyr:

library(dplyr) 

df %>% 
    group_by(rutcli, mes_atras) %>% 
    summarise(min_pay_day=min(pay_day)) %>% 
    dcast(rutcli ~ mes_atras, value.var="min_pay_day") 

    rutcli 1 2 3 4 
1 101 1 5 7 NA 
2 102 18 13 14 NA 
3 103 10 13 NA 7 
+0

Или используйте комбинацию 'dplyr' и' tidyr' и замените последнюю строку 'spread (mes_atras, min_pay_day)' – akrun

1

Вы можете сделать это с aggregate и reshape из пакета stats:

reshape(
     aggregate(pay_day ~ mes_atras + rutcli, data=df, FUN=min), 
     direction='wide', timevar='mes_atras', idvar='rutcli' 
) 
## rutcli pay_day.1 pay_day.2 pay_day.3 pay_day.4 
## 1 101   1  20  15   2 
## 5 102  18  30  NA   3 
## 8 103   2   5  23  16 

Вы можете заменить NA значения с Inf при желании.

Вот мой df:

structure(list(rutcli = c(103L, 103L, 103L, 103L, 103L, 103L, 
102L, 102L, 103L, 102L, 101L, 101L, 101L, 101L, 101L, 103L, 102L, 
101L, 101L, 103L), mes_atras = c(1L, 3L, 4L, 1L, 1L, 2L, 1L, 
4L, 1L, 2L, 2L, 4L, 3L, 2L, 2L, 4L, 4L, 4L, 1L, 2L), pay_day = c(3L, 
23L, 16L, 18L, 2L, 5L, 18L, 3L, 12L, 30L, 20L, 2L, 15L, 24L, 
29L, 24L, 3L, 19L, 1L, 12L)), .Names = c("rutcli", "mes_atras", 
"pay_day"), row.names = c(NA, -20L), class = "data.frame") 
0

Я сделал это с:

my.min <- function (v) {if (length(v) == 0) 0 else min(v)} 
s<-dcast(df, rutcli ~ mes_atras, fun.aggregate = my.min, value.var = 'pay_day') 

И потому, что я знаю, что у меня нет никаких 0: с [s == 0] < - NA

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