How do I convert a dataframe with tests as column names to row elements?

StackOverflow https://stackoverflow.com/questions/22106466

  •  18-10-2022
  •  | 
  •  

Pergunta

I have a number of dataframes in the following format

   t1,t2,t3
p1, 1, 2, 3
p2, 1, 2, 3

I want to convert them to

    tests,obs
p1, t1,   1
p1, t2,   2
p1, t3,   3
p2, t1,   1
p2, t2,   2
p2, t3,   3

What is the general way I can go about doing this? (And how do I go the reverse way? )

Foi útil?

Solução

Here's an alternative in base R.

## Some sample data
mydf <- data.frame(t1 = c(1, 1), t2 = c(2, 2), t3 = c(3, 3), 
                   row.names = c("p1", "p2"))
mydf
#    t1 t2 t3
# p1  1  2  3
# p2  1  2  3

## Wide to long
out <- cbind(rn = rownames(mydf), stack(mydf))
out
#   rn values ind
# 1 p1      1  t1
# 2 p2      1  t1
# 3 p1      2  t2
# 4 p2      2  t2
# 5 p1      3  t3
# 6 p2      3  t3

## Long back to wide
reshape(out, direction = "wide", idvar="rn", timevar="ind")
#   rn values.t1 values.t2 values.t3
# 1 p1         1         2         3
# 2 p2         1         2         3

In the long to wide version, you'll have to put the row names back as row.names and rename the columns if you want the exact version of your input.

To do the same with "reshape2" if the column is not part of your data, but rownames, as they are here, either add them in as a column as suggested by Underminer or use melt(as.matrix(.)) which would automatically take care of things.

library(reshape2)

## Wide to long
out <- melt(as.matrix(mydf))
out
#   Var1 Var2 value
# 1   p1   t1     1
# 2   p2   t1     1
# 3   p1   t2     2
# 4   p2   t2     2
# 5   p1   t3     3
# 6   p2   t3     3

## Long to wide
dcast(out, Var1 ~ Var2, value.var="value")
#   Var1 t1 t2 t3
# 1   p1  1  2  3
# 2   p2  1  2  3

Another option in base R is, of course, reshape (which some people like to avoid). To use reshape, the rownames need to be a column in the data.frame.

mydf$p <- rownames(mydf)
out <- reshape(mydf, direction = "long", idvar="p", 
               varying = c("t1", "t2", "t3"), sep = "")
out
#       p time t
# p1.1 p1    1 1
# p2.1 p2    1 1
# p1.2 p1    2 2
# p2.2 p2    2 2
# p1.3 p1    3 3
# p2.3 p2    3 3

If you have used reshape to make the long form, and you need to go back to the wide form, you don't need to specify other arguments since they are stored as attributes to the resulting object. You can just use:

reshape(out)

If you needed to manually specify the arguments to reshape from long to wide, it would look something like:

reshape(out, direction = "wide", idvar="p", timevar="time")

Outras dicas

Let our dataset, called dat, look like:

   p t1 t2 t3
1 p1  1  2  3
2 p2  1  2  3

Then

library(reshape2)
dat.m <- melt(dat, id.vars = "p")

results in

   p variable value
1 p1       t1     1
2 p2       t1     1
3 p1       t2     2
4 p2       t2     2
5 p1       t3     3
6 p2       t3     3

Then you can sort by whatever column you want.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top