Homayoon
Homayoon

Reputation: 45

Reshaping a grouped data frame with large sets of several successive columns of variables

I'm using a data frame similar to this one:

set.seed(1)
test.df <- data.frame(Treatment= "CI",
                  period = seq(1, 3),
                  subject= 1,
                  X.1. = rnorm(6),
                  X.2. = rnorm(6),
                  X.3. = rnorm(6),
                  Y.1. = rnorm(6),
                  Y.2. = rnorm(6),
                  Y.3. = rnorm(6))
> test.df
  Treatment period subject       X.1.       X.2.        X.3.        Y.1.        Y.2.        Y.3.
1        CI      1       1 -0.6264538  0.4874291 -0.62124058  0.82122120  0.61982575  1.35867955
2        CI      2       1  0.1836433  0.7383247 -2.21469989  0.59390132 -0.05612874 -0.10278773
3        CI      3       1 -0.8356286  0.5757814  1.12493092  0.91897737 -0.15579551  0.38767161
4        CI      1       1  1.5952808 -0.3053884 -0.04493361  0.78213630 -1.47075238 -0.05380504
5        CI      2       1  0.3295078  1.5117812 -0.01619026  0.07456498 -0.47815006 -1.37705956
6        CI      3       1 -0.8204684  0.3898432  0.94383621 -1.98935170  0.41794156 -0.41499456

And I want my data to look like the following:

  Treatment period subject Game           X           Y
1        CI      1       1    1  -0.6264538  0.82122120

where Game is from 1:3 and this has been done for each group of c(Treatment, Period). But in real data, beside X and Y, there are about 16 other similar variables. Inspired by this post, i tried to do it in the following way:

final.df<- test.df %>% 
group_by(Treatment, period) %>%
reshape(idvar=1:3, varying=4:ncol(test.df), sep=".", direction='long',times=1:3)

and I get the following error

Error in `row.names<-.data.frame`(`*tmp*`, value = paste(d[, idvar], times[1L],
  : invalid 'row.names' length

Upvotes: 0

Views: 398

Answers (2)

A5C1D2H2I1M1N2O1R2T1
A5C1D2H2I1M1N2O1R2T1

Reputation: 193667

After fixing the names, you're still left with two problems: (1) your current IDs are not unique; (2) reshape doesn't like tbl_dfs. Thus, you need to do something like the following if you insist on using "dplyr":

names(test.df) <- toupper(names(test.df))
test.df %>% 
  group_by(TREATMENT, PERIOD) %>%
  mutate(NEW_ID = sequence(n())) %>%
  data.frame %>%
  reshape(varying = grep("^X\\.|^Y\\.", names(test.df)), sep=".", direction = "long")
#     TREATMENT PERIOD SUBJECT NEW_ID time            X           Y id
# 1.1        CI      1       1      1    1  0.898037653 -1.62380441  1
# 2.1        CI      2       1      1    1 -0.265867132  1.19260758  2
# 3.1        CI      3       1      1    1  0.478254223  0.37225231  3
# 4.1        CI      1       1      2    1  0.193781526  0.78440441  4
# 5.1        CI      2       1      2    1 -0.785203396 -0.88621250  5
# 6.1        CI      3       1      2    1  0.341740150 -0.67919816  6
# 1.2        CI      1       1      1    2 -1.808196090  1.64211603  1
# 2.2        CI      2       1      1    2 -0.937445606 -0.35388758  2
# 3.2        CI      3       1      1    2  1.773354124  0.95633070  3
# 4.2        CI      1       1      2    2 -0.819681242  1.06421615  4
# 5.2        CI      2       1      2    2  0.003812118 -0.04835364  5
# 6.2        CI      3       1      2    2  0.226081490  0.50687855  6
# 1.3        CI      1       1      1    3  0.822497674 -0.55875020  1
# 2.3        CI      2       1      1    3  0.382695603 -0.83661977  2
# 3.3        CI      3       1      1    3  0.066738811 -1.96761492  3
# 4.3        CI      1       1      2    3  0.854280148 -0.49335882  4
# 5.3        CI      2       1      2    3 -1.635859887  1.18322984  5
# 6.3        CI      3       1      2    3 -0.020864680  1.20997470  6

I would suggest, however, that you look at melt from "data.table" instead:

library(data.table)
melt(as.data.table(setnames(test.df, toupper(names(test.df)))), 
     measure.vars = patterns("^X\\.", "^Y\\."), value.name = c("X", "Y"))
#     TREATMENT PERIOD SUBJECT variable            X           Y
#  1:        CI      1       1        1  0.898037653 -1.62380441
#  2:        CI      2       1        1 -0.265867132  1.19260758
#  3:        CI      3       1        1  0.478254223  0.37225231
#  4:        CI      1       1        1  0.193781526  0.78440441
#  5:        CI      2       1        1 -0.785203396 -0.88621250
#  6:        CI      3       1        1  0.341740150 -0.67919816
#  7:        CI      1       1        2 -1.808196090  1.64211603
#  8:        CI      2       1        2 -0.937445606 -0.35388758
#  9:        CI      3       1        2  1.773354124  0.95633070
# 10:        CI      1       1        2 -0.819681242  1.06421615
# 11:        CI      2       1        2  0.003812118 -0.04835364
# 12:        CI      3       1        2  0.226081490  0.50687855
# 13:        CI      1       1        3  0.822497674 -0.55875020
# 14:        CI      2       1        3  0.382695603 -0.83661977
# 15:        CI      3       1        3  0.066738811 -1.96761492
# 16:        CI      1       1        3  0.854280148 -0.49335882
# 17:        CI      2       1        3 -1.635859887  1.18322984
# 18:        CI      3       1        3 -0.020864680  1.20997470

Upvotes: 2

TheRimalaya
TheRimalaya

Reputation: 4592

df.stk <- tidyr::gather(test.df, "xy", "value", -Treatment:-subject)
    df.sep <- tidyr::separate(df.stk, "xy", c("xy", "Game", "temp"), sep="\\.")[, -6]
    df.final <- reshape2::dcast(df.sep, Treatment + period + subject + Game ~ xy, fun.aggregate=mean)

But you need to make all your X and Y name either lowercase or uppercase

Upvotes: 0

Related Questions