R: Calculate rowwise lm() over multiple variables

Viewed 267

How can I calculate the row-wise lm() / coeffs of multiple variables in an df, which are stored in columns?

I have this kind of data (just examples):

set.seed(1)
foo <- data.frame(trialNumber= 1:10, 
Nr1 = runif(10), 
Nr2 = runif(10), 
Nr3 = runif(10), 
Nr4 = runif(10), 
Nr5 = runif(10), 
Nr6 = runif(10), 
slope = NA)

The trialNumber represents each one of a trial where I measured six values directly behind each other.

I managed to plot these data with a linear regression line with boxplots using this code:

foo_1 <- reshape2::melt(data = foo, id.vars = "trialNumber", measure.vars = c("Nr1", "Nr2", "Nr3", "Nr4", "Nr5", "Nr6"))

p <- ggplot(data = foo_1) + 
  aes(x = variable,
      y = value) + 
  geom_boxplot() + 
  geom_jitter(shape = 1, position = position_jitter(0.1)) +
  ylim(0, NA) + 
  geom_smooth(method = "lm", se = TRUE, formula = y ~ x, aes(group = 1)) 

print(p)

which results in this diagram:

enter image description here

Now this is the linear regression line of all the trials, but I want the slope (or regression coefficients) row-wise stored in the variable "slope".

In the end I want a df like this:

trialnumber | Nr1 | Nr2 | Nr3 | Nr4 | Nr5 | Nr6 | slope
1           | 0.26550866 | 0.2059746|0.93470523|0.4820801|0.8209463|0.47761962|e.g. 0.07
2           | ?   | ?   | ?   | ?   | ?   | ?   |e.g. 3.81
.
.
.

How can I achieve this? I already looked into the apply function, but I could not figure out how to use this.

Thank you very much in advance!

2 Answers
bar <- reshape2::melt(foo[,-8], id.var = "trialNumber")

#create x values
#this assumes that the column names are exactly as shown
bar$variable <- as.integer(bar$variable)

library(nlme)
fit <- lmList(value ~ variable | trialNumber, data = bar)

#this assumes trial numbers are sorted in foo
foo$slope <- coef(fit)[, "variable"]

You can indeed just use apply. This only requires that you know the indices of your columns. Here I have specified 2:7, but for your own data you could get the correct indices by specifying for example grep("Nr", names(foo)). You need to make sure the columns are in the correct order in your data frame though, as they are in your example.

foo$slope <- apply(foo[2:7], 1, function(x) coef(lm(x ~ seq(x)))[2])

foo
#>    trialNumber        Nr1       Nr2        Nr3       Nr4       Nr5        Nr6
#> 1            1 0.26550866 0.2059746 0.93470523 0.4820801 0.8209463 0.47761962
#> 2            2 0.37212390 0.1765568 0.21214252 0.5995658 0.6470602 0.86120948
#> 3            3 0.57285336 0.6870228 0.65167377 0.4935413 0.7829328 0.43809711
#> 4            4 0.90820779 0.3841037 0.12555510 0.1862176 0.5530363 0.24479728
#> 5            5 0.20168193 0.7698414 0.26722067 0.8273733 0.5297196 0.07067905
#> 6            6 0.89838968 0.4976992 0.38611409 0.6684667 0.7893562 0.09946616
#> 7            7 0.94467527 0.7176185 0.01339033 0.7942399 0.0233312 0.31627171
#> 8            8 0.66079779 0.9919061 0.38238796 0.1079436 0.4772301 0.51863426
#> 9            9 0.62911404 0.3800352 0.86969085 0.7237109 0.7323137 0.66200508
#> 10          10 0.06178627 0.7774452 0.34034900 0.4112744 0.6927316 0.40683019
#>          slope
#> 1   0.07008128
#> 2   0.12126747
#> 3  -0.01554811
#> 4  -0.07855978
#> 5  -0.02329221
#> 6  -0.08106554
#> 7  -0.12697229
#> 8  -0.07226543
#> 9   0.03072317
#> 10  0.04405726

Related