2

I performed a transformation of a data frame using the following code and I want to replicate it in five more data frames:

`df_1` <- as.data.frame(sapply(`df_1`[-1], function(col) ave(col, FUN=function(x) ((x / x[1]))*100)))

The names of all existing data frames are stored in a vector called data_frames. Clarification: All data frames have the same number of rows and columns.

data_frames <- ls(pattern = "df *")

I tried to do this but when I ran the code they return an error.

for (k in data_frames){
           k <- as.data.frame(sapply(k[-1], function(col) ave(col, FUN=function(x) ((x /          x[1]))*100)))

I desire to rewrite the existing data frames with the new transformation. Thanks a lot!

stefan
  • 90,330
  • 6
  • 25
  • 51
  • Just use get: `for (k in data_frames){ k <- as.data.frame(sapply(get(k)[-1], function(col) ave(col, FUN=function(x) ((x / x[1]))*100))) } ` – Ric Nov 14 '22 at 20:52
  • Another way: `for (k in mget(data_frames)){ k <- as.data.frame(sapply(k[-1], function(col) ave(col, FUN=function(x) ((x / x[1]))*100))) }` – Ric Nov 14 '22 at 20:53
  • Don't just grab the names, [put the data frames in a list](https://stackoverflow.com/questions/17499013/how-do-i-make-a-list-of-data-frames). – Gregor Thomas Nov 14 '22 at 21:11

1 Answers1

0

There are several solutions for this problem, here is a base R solution:

Setup

df1 <- df2 <- df3 <- df4 <- mtcars[1:4, 1:3]
### store all relevant data.frames in a list
df_nms <- ls(pattern = "^df[0-9]$")

Base R

df1

#                 mpg cyl disp
# Mazda RX4      21.0   6  160
# Mazda RX4 Wag  21.0   6  160
# Datsun 710     22.8   4  108
# Hornet 4 Drive 21.4   6  258


for (nm in df_nms) {
   tmp <- get(nm)
   tmp[-1] <- lapply(tmp[-1], function(x) ave(x, FUN = function(x) x / x[1] * 100))
   assign(nm, tmp)
}

df1

#                 mpg       cyl   disp
# Mazda RX4      21.0 100.00000 100.00
# Mazda RX4 Wag  21.0 100.00000 100.00
# Datsun 710     22.8  66.66667  67.50
# Hornet 4 Drive 21.4 100.00000 161.25

Howevr, using assign is usually not a good design pattern, and I'd rather work with a list of data frames and change the list instead of the original values:

lapply(mget(df_nms), 
       function(df) {
          df[-1] <- lapply(df[-1], 
                           function(x) ave(x, FUN = function(x) x / x[1] * 100))
          df})

# $df1
#                 mpg       cyl   disp
# Mazda RX4      21.0 100.00000 100.00
# Mazda RX4 Wag  21.0 100.00000 100.00
# Datsun 710     22.8  66.66667  67.50
# Hornet 4 Drive 21.4 100.00000 161.25

# $df2
#                 mpg       cyl   disp
# Mazda RX4      21.0 100.00000 100.00
# Mazda RX4 Wag  21.0 100.00000 100.00
# Datsun 710     22.8  66.66667  67.50
# Hornet 4 Drive 21.4 100.00000 161.25

# $df3
#                 mpg       cyl   disp
# Mazda RX4      21.0 100.00000 100.00
# Mazda RX4 Wag  21.0 100.00000 100.00
# Datsun 710     22.8  66.66667  67.50
# Hornet 4 Drive 21.4 100.00000 161.25

# $df4
#                 mpg       cyl   disp
# Mazda RX4      21.0 100.00000 100.00
# Mazda RX4 Wag  21.0 100.00000 100.00
# Datsun 710     22.8  66.66667  67.50
# Hornet 4 Drive 21.4 100.00000 161.25
thothal
  • 16,690
  • 3
  • 36
  • 71