Reputation: 2157
I have the following list of dataframes
d1 <- data.frame(var1 = 10, var2 = 20, var3 = 30)
d2 <- data.frame(var4 = 40, var5 = 50, var6 = 60)
my.list <- list(d1, d2)
> my.list
[[1]]
var1 var2 var3
1 10 20 30
[[2]]
var4 var5 var6
1 40 50 60
Now I want to add new rows to each of these dataframes that contain the following content:
values <- c(0.75, 0.5, 0.25)
d1$var1 * values[1] #new second row d1
d1$var1 * values[2] #new third row d1
d1$var1 * values[3] #new fourth row d1
This needs to be done for all $var variables in each dataframe and all dataframes in the list.
the new d1 would look like this:
var1 var2 var3
1 10 20 30
2 7.5 15 22.5
3 5 10 15
4 2.5 5 7.5
How could I achieve this?
Upvotes: 3
Views: 599
Reputation: 11255
Here's an interesting use of rapply()
.
rapply(my.list, function(x) c(x,x*values), how = 'list')
[[1]]
[[1]]$var1
[1] 10.0 7.5 5.0 2.5
[[1]]$var2
[1] 20 15 10 5
[[1]]$var3
[1] 30.0 22.5 15.0 7.5
[[2]]
[[2]]$var4
[1] 40 30 20 10
[[2]]$var5
[1] 50.0 37.5 25.0 12.5
[[2]]$var6
[1] 60 45 30 15
You can get it back to your intended output by wrapping it in lapply(..., data.frame)
lapply(rapply(my.list, function(x) c(x,x*values), how = 'list' ), data.frame)
[[1]]
var1 var2 var3
1 10.0 20 30.0
2 7.5 15 22.5
3 5.0 10 15.0
4 2.5 5 7.5
[[2]]
var4 var5 var6
1 40 50.0 60
2 30 37.5 45
3 20 25.0 30
4 10 12.5 15
The rapply()
itself is faster but it loses all advantages after the result is coerced back to a data.frame.
Upvotes: 0
Reputation: 13319
Almost similar to @akrun 's, we can do(might be more computationally expensive and also has the disadvantage of forming a matrix) :
lapply(my.list,sapply,function(x) append(x,
do.call(`*`,list(x,values))))
[[1]]
var1 var2 var3
[1,] 10.0 20 30.0
[2,] 7.5 15 22.5
[3,] 5.0 10 15.0
[4,] 2.5 5 7.5
[[2]]
var4 var5 var6
[1,] 40 50.0 60
[2,] 30 37.5 45
[3,] 20 25.0 30
[4,] 10 12.5 15
Upvotes: 2
Reputation: 887128
An option would be to loop over the list
and multiply each column with the 'values' vector and rbind
the original data row with the new row
lapply(my.list, function(x) rbind(x, sapply(x, `*`, values)))
#[[1]]
# var1 var2 var3
#1 10.0 20 30.0
#2 7.5 15 22.5
#3 5.0 10 15.0
#4 2.5 5 7.5
#[[2]]
# var4 var5 var6
#1 40 50.0 60
#2 30 37.5 45
#3 20 25.0 30
#4 10 12.5 15
Or an option with tidyverse
using add_row
and map
library(tidyverse)
map(my.list, ~ .x %>%
add_row(!!! map(., `*`, values)))
#[[1]]
# var1 var2 var3
#1 10.0 20 30.0
#2 7.5 15 22.5
#3 5.0 10 15.0
#4 2.5 5 7.5
#[[2]]
# var4 var5 var6
#1 40 50.0 60
#2 30 37.5 45
#3 20 25.0 30
#4 10 12.5 15
Upvotes: 5