简体   繁体   中英

How to reshape a data frame from wide to long format in R?

I am new to R. I am trying to read data from Excel in the mentioned format

x1  x2  x3  y1  y2  y3  Result
1   2   3   7   8   9    
4   5   6   10  11  12   

and data.frame in R should take data in mentioned format for 1st row

x   y
1   7
2   8
3   9

then I want to use lm() and export the result to result column.

I want to automate this for n rows ie once results of 1st column is exported to Excel then I want to import data for second row.

Please Help.

library(gdata)
# this spreadsheet is exactly as in your question

df.original <- read.xls("test.xlsx", sheet="Sheet1", perl="C:/strawberry/perl/bin/perl.exe")
#
#
> df.original
  x1 x2 x3 y1 y2 y3
1  1  2  3  7  8  9
2  4  5  6 10 11 12
#
# for the above code you'll just need to change the argument 'perl' with the
# path of your installer
#
# now the example for the first row
#
library(reshape2)

df <- melt(df.original[1,])

df$variable <- substr(df$variable, 1, 1)

df <- as.data.frame(lapply(split(df, df$variable), `[[`, 2))

> df
  x y
1 1 7
2 2 8
3 3 9

Now, at this stage we automated the process of inport/transformation (for one line).

First question: How you want the data to look like when every line will be treated? Second question: In result, what do you want exactly to put? residual, fitted values? what you need from lm() ?

EDIT:

ok, @kapil tell me if the final shape of df is what you thought:

library(reshape2)
library(plyr)

df <- adply(df.original, 1, melt, .expand=F)
names(df)[1] <- "rowID"

df$variable <- substr(df$variable, 1, 1)

rows <- df$rowID[ df$variable=="x"] # with y would be the same (they are expected to have the same legnth)
df <- as.data.frame(lapply(split(df, df$variable), `[[`, c("value")))
df$rowID <- rows

df <- df[c("rowID", "x", "y")]

> df
  rowID x  y
1     1 1  7
2     1 2  8
3     1 3  9
4     2 4 10
5     2 5 11
6     2 6 12

regarding the coefficient you can calculate for each rowID (which refers to the actual row in the xls file) in this way:

model <- dlply(df, .(rowID), function(z) {print(z); lm(y ~ x, df);})

> sapply(model, `[`, "coefficients")
$`1.coefficients`
(Intercept)           x 
          6           1 

$`2.coefficients`
(Intercept)           x 
          6           1 

so, for each group (or row in original spreadsheet) you have (as expected) two coefficients, intercept and slope, therefore I can't figure out how you want the coefficient to fit inside the data.frame (especially in the 'long' way it appears just above). But if you wanted the data.frame to stay in 'wide' mode then you can try this:

# obtained the object model, you can put the coeff in the df.original data.frame
#
> ldply(model, `[[`, "coefficients")
  rowID (Intercept) x
1     1           6 1
2     2           6 1

df.modified <- cbind(df.original, ldply(model, `[[`, "coefficients"))

> df.modified
  x1 x2 x3 y1 y2 y3 rowID (Intercept) x
1  1  2  3  7  8  9     1           6 1
2  4  5  6 10 11 12     2           6 1

# of course, if you don't like it, you can remove rowID with df.modified$rowID <- NULL

Hope this helps, and let me know if you wanted the 'long' version of df.

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