简体   繁体   中英

R- ddply: dates transformed to numbers when summarized

I have a table with different dates for id_client. I need to create a table with all dates between maximum and minumun date of each client. For example, my table would be:

tbl<-data.frame(id_cliente=c(1,1,1,1,2,3,3,3), 
                fecha=c('2013-01-01', '2013-06-01','2013-05-01', '2013-04-01', 
                        '2013-01-01', '2013-01-01','2013-05-01','2013-04-01'))

tbl$fecha<-as.Date(as.character(tbl$fecha))

I need to end up with a table like:

id_cliente  fecha
1   01/01/2013
1   01/02/2013
1   01/03/2013
1   01/04/2013
1   01/05/2013
1   01/06/2013
2   01/01/2013
3   01/01/2013
3   01/02/2013
3   01/03/2013
3   01/04/2013
3   01/05/2013

I thought I could use ddply (plyr package), so I created a function that gets the sequence of months:

meses<-function(xMin, xMax){ 
  seq(from=as.Date(xMin, , '%Y-%m-%d'), to=as.Date(xMax, '%Y-%m-%d'), by='month')}

Then I apply ddply:

library(plyr)
vf<-ddply(tbl, .(id_cliente), summarize, maxF=max(fecha), minF=min(fecha), 
                 sec=list(meses(xMin=minF, xMax=maxF)))

But my table is:

> vf
  id_cliente       maxF       minF                                      sec
1          1 2013-06-01 2013-01-01 15706, 15737, 15765, 15796, 15826, 15857
2          2 2013-01-01 2013-01-01                                    15706
3          3 2013-05-01 2013-01-01        15706, 15737, 15765, 15796, 15826

Dates stored in the list are transformed to numbers.

I know I can transform a number to a date. So:

convFecha<-function(x){as.Date(x, origin='1970-01-01')}

And then I used lapply:

lapply(vf$sec, convFecha)

And I get the desired result:

[[1]]
[1] "2013-01-01" "2013-02-01" "2013-03-01" "2013-04-01" "2013-05-01" "2013-06-01"

[[2]]
[1] "2013-01-01"

[[3]]
[1] "2013-01-01" "2013-02-01" "2013-03-01" "2013-04-01" "2013-05-01"

At this point I dont know how to create the final table. If I try to paste this result to my table it transforms the dates again in numbers.

vf$sec1<-lapply(vf$sec, convFecha)

So, do I have to paste these dates to each row of vf ? Is there any other way yo get the desired table? What would be the next step to reach the table needed?

That's not a full answer, but a first step using by function

out <- by(tbl, list(tbl$id_cliente), 
          function(x) seq(from=as.Date(min(x$fecha), , '%Y-%m-%d'), 
                          to=as.Date(max(x$fecha), '%Y-%m-%d'), by='month'))

> out 
: 1
[1] "2013-01-01" "2013-02-01" "2013-03-01" "2013-04-01" "2013-05-01"
[6] "2013-06-01"
------------------------------------------------------- 
: 2
[1] "2013-01-01"
------------------------------------------------------- 
: 3
[1] "2013-01-01" "2013-02-01" "2013-03-01" "2013-04-01" "2013-05-01"

Here is my try,

tbl <- data.frame(id_cliente = c(1, 1, 1, 1, 2, 3, 3, 3), 
                  fecha = c('2013-01-01', '2013-06-01', '2013-05-01', '2013-04-01', 
                            '2013-01-01', '2013-01-01', '2013-05-01', '2013-04-01'))

ddply(tbl, .(id_cliente), function(d) {
    xMin <- min(as.Date(d$fecha))
    xMax <- max(as.Date(d$fecha))
    data.frame(fecha = format(seq(from=xMin, to=xMax, by='month'), format = "%d/%m/%Y"))
})

output:

   id_cliente      fecha
1           1 01/01/2013
2           1 01/02/2013
3           1 01/03/2013
4           1 01/04/2013
5           1 01/05/2013
6           1 01/06/2013
7           2 01/01/2013
8           3 01/01/2013
9           3 01/02/2013
10          3 01/03/2013
11          3 01/04/2013
12          3 01/05/2013

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM