Blind0ne
Blind0ne

Reputation: 1037

Dcast or Reshape dataframe in R

I have a dataframe like this:

originalDF <- data.frame(A1=c(1, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6), 
                         A2=c(12.2, 12.2, 15.0, 34.123, 2.0, 66.0, 7.0, 7.0, 7.0, 7.0, 7.0), 
                         A3=c('T1', 'T2', 'T1', 'T1', 'T2', 'T1', 'T1', 'T1', 'T1', 'T1', 'T1'), 
                         A4=c('1234', '1234', '1234', '1234', '4321', '4321', '4321', '4321', '4321', '4321', '4321'),
                         A5=c('0245', '0245', '0500', '0500', '0600', '0600', '0600','0800','0700','0900', '0900'))

   A1     A2 A3   A4   A5
1   1 12.200 T1 1234 0245
2   1 12.200 T2 1234 0245
3   2 15.000 T1 1234 0500
4   3 34.123 T1 1234 0500
5   4  2.000 T2 4321 0600
6   5 66.000 T1 4321 0600
7   6  7.000 T1 4321 0600
8   6  7.000 T1 4321 0800
9   6  7.000 T1 4321 0700
10  6  7.000 T1 4321 0900
11  6  7.000 T1 4321 0900

I want now to reshape it that it finally looks like this:

wantedDF <- cbind.data.frame(originalDF, 
                              A3_0245=c('T1', 'T2', NA, NA, NA, NA, NA, NA, NA, NA, NA), 
                              A3_0500=c(NA, NA, 'T1', 'T1', NA, NA, NA, NA, NA, NA, NA), 
                              A3_0600=c(NA, NA, NA, NA, 'T2', 'T1', 'T1', NA, NA, NA, NA), 
                              A3_0800=c(NA, NA, NA, NA, NA, NA, NA, 'T1', NA, NA, NA), 
                              A3_0700=c(NA, NA, NA, NA, NA, NA, NA, NA, 'T1', NA, NA), 
                              A3_0900=c(NA, NA, NA, NA, NA, NA, NA, NA, NA, 'T1', 'T1'))

   A1     A2 A3   A4   A5 A3_0245 A3_0500 A3_0600 A3_0800 A3_0700 A3_0900
1   1 12.200 T1 1234 0245      T1    <NA>    <NA>    <NA>    <NA>    <NA>
2   1 12.200 T2 1234 0245      T2    <NA>    <NA>    <NA>    <NA>    <NA>
3   2 15.000 T1 1234 0500    <NA>      T1    <NA>    <NA>    <NA>    <NA>
4   3 34.123 T1 1234 0500    <NA>      T1    <NA>    <NA>    <NA>    <NA>
5   4  2.000 T2 4321 0600    <NA>    <NA>      T2    <NA>    <NA>    <NA>
6   5 66.000 T1 4321 0600    <NA>    <NA>      T1    <NA>    <NA>    <NA>
7   6  7.000 T1 4321 0600    <NA>    <NA>      T1    <NA>    <NA>    <NA>
8   6  7.000 T1 4321 0800    <NA>    <NA>    <NA>      T1    <NA>    <NA>
9   6  7.000 T1 4321 0700    <NA>    <NA>    <NA>    <NA>      T1    <NA>
10  6  7.000 T1 4321 0900    <NA>    <NA>    <NA>    <NA>    <NA>      T1
11  6  7.000 T1 4321 0900    <NA>    <NA>    <NA>    <NA>    <NA>      T1

How can I achieve this? I already asked a kinda similar question here but I can't get to work it :(. This is what I already tried:

DfNames <- unique(originalDF$A5)
wantedDF[,sprintf('A3_%s',DfNames )] <- NA

(now I need conditional add to the each column)

(Base R and data.table solutions preferred!) Thanks in advance!

Upvotes: 2

Views: 309

Answers (3)

BENY
BENY

Reputation: 323376

#You can try this. 

    library(reshape2)
    originalDF <- data.frame(A1=c(1, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6), 
                             A2=c(12.2, 12.2, 15.0, 34.123, 2.0, 66.0, 7.0, 7.0, 7.0, 7.0, 7.0), 
                             A3=c('T1', 'T2', 'T1', 'T1', 'T2', 'T1', 'T1', 'T1', 'T1', 'T1', 'T1'), 
                             A4=c('1234', '1234', '1234', '1234', '4321', '4321', '4321', '4321', '4321', '4321', '4321'),
                             A5=c('0245', '0245', '0500', '0500', '0600', '0600', '0600','0800','0700','0900', '0900'),stringsAsFactors = F)
    originalDF$Ind=as.numeric(row.names(originalDF))
    DF=(acast(originalDF, Ind~paste('A3_',A5), value.var="A3"))    
    originalDF=cbind(originalDF,DF)


> originalDF
   A1     A2 A3   A4   A5 Ind A3_ 0245 A3_ 0500 A3_ 0600 A3_ 0700 A3_ 0800 A3_ 0900
1   1 12.200 T1 1234 0245   1   T1 <NA> <NA> <NA> <NA> <NA>
2   1 12.200 T2 1234 0245   2   T2 <NA> <NA> <NA> <NA> <NA>
3   2 15.000 T1 1234 0500   3 <NA>   T1 <NA> <NA> <NA> <NA>
4   3 34.123 T1 1234 0500   4 <NA>   T1 <NA> <NA> <NA> <NA>
5   4  2.000 T2 4321 0600   5 <NA> <NA>   T2 <NA> <NA> <NA>
6   5 66.000 T1 4321 0600   6 <NA> <NA>   T1 <NA> <NA> <NA>
7   6  7.000 T1 4321 0600   7 <NA> <NA>   T1 <NA> <NA> <NA>
8   6  7.000 T1 4321 0800   8 <NA> <NA> <NA> <NA>   T1 <NA>
9   6  7.000 T1 4321 0700   9 <NA> <NA> <NA>   T1 <NA> <NA>
10  6  7.000 T1 4321 0900  10 <NA> <NA> <NA> <NA> <NA>   T1
11  6  7.000 T1 4321 0900  11 <NA> <NA> <NA> <NA> <NA>   T1

Upvotes: 2

Eric Watt
Eric Watt

Reputation: 3240

Using data.table and dcast.

library(data.table)

dat <- data.table(A1=c(1, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6), 
                         A2=c(12.2, 12.2, 15.0, 34.123, 2.0, 66.0, 7.0, 7.0, 7.0, 7.0, 7.0), 
                         A3=c('T1', 'T2', 'T1', 'T1', 'T2', 'T1', 'T1', 'T1', 'T1', 'T1', 'T1'), 
                         A4=c('1234', '1234', '1234', '1234', '4321', '4321', '4321', '4321', '4321', '4321', '4321'),
                         A5=c('0245', '0245', '0500', '0500', '0600', '0600', '0600','0800','0700','0900', '0900'))

dat2 <- dcast(dat, 
              A1 + A2 + A3 + A4 + A5 ~ A5, 
              value.var = "A3", 
              fun = function(x) x, 
              fill = NA)

Results in:

    A1     A2 A3   A4   A5 0245 0500 0600 0700 0800 0900
 1:  1 12.200 T1 1234 0245   T1   NA   NA   NA   NA   NA
 2:  1 12.200 T2 1234 0245   T2   NA   NA   NA   NA   NA
 3:  2 15.000 T1 1234 0500   NA   T1   NA   NA   NA   NA
 4:  3 34.123 T1 1234 0500   NA   T1   NA   NA   NA   NA
 5:  4  2.000 T2 4321 0600   NA   NA   T2   NA   NA   NA
 6:  5 66.000 T1 4321 0600   NA   NA   T1   NA   NA   NA
 7:  6  7.000 T1 4321 0600   NA   NA   T1   NA   NA   NA
 8:  6  7.000 T1 4321 0700   NA   NA   NA   T1   NA   NA
 9:  6  7.000 T1 4321 0800   NA   NA   NA   NA   T1   NA
10:  6  7.000 T1 4321 0900   NA   NA   NA   NA   NA   T1

You'll notice that row 11 is missing. This is because 10 and 11 were dups. You can always use merge to pull these back in.

merge(dat,
      dat2,
      by = c("A1", "A2", "A3", "A4", "A5"),
      all.x = TRUE)

    A1     A2 A3   A4   A5 0245 0500 0600 0700 0800 0900
 1:  1 12.200 T1 1234 0245   T1   NA   NA   NA   NA   NA
 2:  1 12.200 T2 1234 0245   T2   NA   NA   NA   NA   NA
 3:  2 15.000 T1 1234 0500   NA   T1   NA   NA   NA   NA
 4:  3 34.123 T1 1234 0500   NA   T1   NA   NA   NA   NA
 5:  4  2.000 T2 4321 0600   NA   NA   T2   NA   NA   NA
 6:  5 66.000 T1 4321 0600   NA   NA   T1   NA   NA   NA
 7:  6  7.000 T1 4321 0600   NA   NA   T1   NA   NA   NA
 8:  6  7.000 T1 4321 0700   NA   NA   NA   T1   NA   NA
 9:  6  7.000 T1 4321 0800   NA   NA   NA   NA   T1   NA
10:  6  7.000 T1 4321 0900   NA   NA   NA   NA   NA   T1
11:  6  7.000 T1 4321 0900   NA   NA   NA   NA   NA   T1

You can also easily set the column names:

setnames(dat2, unique(dat$A5), paste("A3", unique(dat$A5), sep = "_"))

    A1     A2 A3   A4   A5 A3_0245 A3_0500 A3_0600 A3_0700 A3_0800 A3_0900
 1:  1 12.200 T1 1234 0245      T1      NA      NA      NA      NA      NA
 2:  1 12.200 T2 1234 0245      T2      NA      NA      NA      NA      NA
 3:  2 15.000 T1 1234 0500      NA      T1      NA      NA      NA      NA
 4:  3 34.123 T1 1234 0500      NA      T1      NA      NA      NA      NA
 5:  4  2.000 T2 4321 0600      NA      NA      T2      NA      NA      NA
 6:  5 66.000 T1 4321 0600      NA      NA      T1      NA      NA      NA
 7:  6  7.000 T1 4321 0600      NA      NA      T1      NA      NA      NA
 8:  6  7.000 T1 4321 0700      NA      NA      NA      T1      NA      NA
 9:  6  7.000 T1 4321 0800      NA      NA      NA      NA      T1      NA
10:  6  7.000 T1 4321 0900      NA      NA      NA      NA      NA      T1
11:  6  7.000 T1 4321 0900      NA      NA      NA      NA      NA      T1

Upvotes: 1

mt1022
mt1022

Reputation: 17299

A data.table solution:

library(data.table)

dt <- as.data.table(originalDF)
dt[, toc := paste('A3', A5, sep = '_')]

res <- dcast(dt, A1 + A2 + A3 + A4 + A5 + rowid(A1) ~ toc, value.var = 'A3')[, A1_1 := NULL]
# > res[]
#     A1     A2 A3   A4   A5 A3_0245 A3_0500 A3_0600 A3_0700 A3_0800 A3_0900
#  1:  1 12.200 T1 1234 0245      T1      NA      NA      NA      NA      NA
#  2:  1 12.200 T2 1234 0245      T2      NA      NA      NA      NA      NA
#  3:  2 15.000 T1 1234 0500      NA      T1      NA      NA      NA      NA
#  4:  3 34.123 T1 1234 0500      NA      T1      NA      NA      NA      NA
#  5:  4  2.000 T2 4321 0600      NA      NA      T2      NA      NA      NA
#  6:  5 66.000 T1 4321 0600      NA      NA      T1      NA      NA      NA
#  7:  6  7.000 T1 4321 0600      NA      NA      T1      NA      NA      NA
#  8:  6  7.000 T1 4321 0700      NA      NA      NA      T1      NA      NA
#  9:  6  7.000 T1 4321 0800      NA      NA      NA      NA      T1      NA
# 10:  6  7.000 T1 4321 0900      NA      NA      NA      NA      NA      T1
# 11:  6  7.000 T1 4321 0900      NA      NA      NA      NA      NA      T1

Upvotes: 2

Related Questions