简体   繁体   中英

Apply different rounding rules to each dataframe in a list of dataframes R

I have a list of around 30 dataframes. I calculate various statistics (mean, sd, median, etc) on the values within each dataframe using lapply and save as a new dataframe

Each dataframe within the list of the dataframes represents chemistry information and has different requirements in how many decimal places are displayed for the the calculated statistics. I also have a requirement that if a given analyte is to be displayed to 3 decimal places then a value of 23.2 must be 23.200. I am able to set the same decimal places across all dataframes but specific to my requirements.

I can use the format function on a vector to get the decimal places I want such as

myvector <- runif(10,1,90)
newVector <- format(round(myvector ,3),nsmall = 3) #make decimal places 3

I believe the way forward is to use a list that can be somehow passed on to get the desired result.

an example of my list of dataframes below

list(Fe = structure(list(Determination_No = 1:6, `2` = c(55.94, 
55.7, 56.59, 56.5, 55.98, 55.93), `3` = c(56.83, 56.54, 56.18, 
56.5, 56.51, 56.34), `4` = c(56.39, 56.43, 56.53, 56.31, 56.47, 
56.35), `5` = c(56.32, 56.29, 56.31, 56.32, 56.39, 56.32), `7` = c(56.48, 
56.4, 56.54, 56.43, 56.73, 56.62), `8` = c(56.382, 56.258, 56.442, 
56.258, 56.532, 56.264), `10` = c(56.3, 56.5, 56.2, 56.5, 56.7, 
56.5), `12` = c(56.11, 56.46, 56.1, 56.35, 56.36, 56.37)), class = "data.frame", row.names = c(NA, 
-6L)), SiO2 = structure(list(Determination_No = 1:6, `2` = c(7.63, 
7.65, 7.73, 7.67, 7.67, 7.67), `3` = c(7.84, 7.69, 7.59, 7.77, 
7.74, 7.64), `4` = c(7.67, 7.74, 7.62, 7.81, 7.66, 7.8), `5` = c(7.91, 
7.84, 7.96, 7.87, 7.84, 7.92), `7` = c(7.77, 7.83, 7.76, 7.78, 
7.65, 7.74), `8` = c(7.936, 7.685, 7.863, 7.838, 7.828, 7.767
), `10` = c(7.872684992, 7.851291827, 7.872684992, 7.722932832, 
7.680146501, 7.615967003), `12` = c(7.64, 7.71, 7.71, 7.65, 7.82, 
7.68)), class = "data.frame", row.names = c(NA, -6L)), Al2O3 = structure(list(
    Determination_No = 1:6, `2` = c(2.01, 2.02, 2.03, 2.01, 2.02, 
    2), `3` = c(2.01, 2.01, 2, 2.02, 2.02, 2.03), `4` = c(2, 
    2.03, 1.99, 2.01, 2.01, 2.01), `5` = c(2.02, 2.02, 2.05, 
    2.03, 2.02, 2.03), `7` = c(1.88, 1.9, 1.89, 1.88, 1.88, 1.87
    ), `8` = c(2.053, 2.044, 2.041, 2.038, 2.008, 2.02), `10` = c(2.002830415, 
    2.021725042, 2.021725042, 1.983935789, 2.002830415, 2.021725042
    ), `12` = c(2.09, 2.05, 1.96, 2.09, 2.06, 2.02)), class = "data.frame", row.names = c(NA, 
-6L)), TiO2 = structure(list(Determination_No = 1:6, `2` = c(0.07, 
0.07, 0.07, 0.07, 0.07, 0.07), `3` = c(0.06, 0.06, 0.06, 0.06, 
0.06, 0.06), `4` = c(0.07, 0.07, 0.07, 0.07, 0.07, 0.07), `5` = c(0.07, 
0.07, 0.07, 0.07, 0.07, 0.07), `7` = c(0.07, 0.07, 0.07, 0.06, 
0.07, 0.06), `8` = c(0.073, 0.07, 0.081, 0.072, 0.07, 0.071), 
    `10` = c(0.066721378, 0.066721378, 0.066721378, 0.066721378, 
    0.066721378, 0.066721378), `12` = c(0.082, 0.079, 0.073, 
    0.077, 0.08, 0.077)), class = "data.frame", row.names = c(NA, 
-6L)), Mn = structure(list(Determination_No = 1:6, `2` = c(0.194, 
0.209, 0.218, 0.22, 0.213, 0.217), `3` = c(0.222, 0.214, 0.21, 
0.212, 0.205, 0.213), `4` = c(0.21, 0.21, 0.21, 0.22, 0.23, 0.2
), `5` = c(0.23, 0.21, 0.22, 0.21, 0.2, 0.22), `7` = c(0.197, 
0.238, 0.205, 0.223, 0.205, 0.214), `8` = c(0.217, 0.221, 0.237, 
0.213, 0.227, 0.232), `10` = c(0.21, 0.21, 0.22, 0.23, 0.21, 
0.22), `12` = c(0.27, 0.24, 0.23, 0.23, 0.22, 0.23)), class = "data.frame", row.names = c(NA, 
-6L)), CaO = structure(list(Determination_No = 1:6, `2` = c(0.08, 
0.07, 0.07, 0.07, 0.08, 0.07), `3` = c(0.08, 0.07, 0.07, 0.07, 
0.07, 0.07), `4` = c(0.07, 0.06, 0.06, 0.07, 0.06, 0.06), `5` = c(0.08, 
0.07, 0.08, 0.07, 0.07, 0.07), `7` = c(0.08, 0.08, 0.07, 0.08, 
0.08, 0.08), `8` = c(0.07, 0.071, 0.07, 0.067, 0.071, 0.07), 
    `10` = c(0.069959326, 0.069959326, 0.069959326, 0.069959326, 
    0.069959326, 0.069959326), `12` = c(0.09, 0.09, 0.34, 0.09, 
    0.09, 0.08)), class = "data.frame", row.names = c(NA, -6L
)))

I have the following function to calculate SD and set to 3 decimals places

LabSD <- function(x,...){
  lab.SD <- round(mapply(sd, x[-1], na.rm = T), digits = 3)
  SD.All <- unlist(x[-1]) #convert all the values to a vector
  lab.SD.T <- format(round(lab.SD ,3),nsmall = 3)
  lab.SD.All <- round(sd(SD.All, na.rm = T), digits = 3)
  lab.SD.All.T <- format(round(lab.SD.All,3),nsmall = 3)
  lab.SDSummary <- c(lab.SD.T, lab.SD.All.T)
  return(lab.SDSummary)
}

Then use lapply to apply to my list of dataframes

df.LabSD <- lapply(df, function(x) LabSD(x,na.rm=T))

I have created a list of for the decimal places i want for each analyte and whether its for the mean value or standard deviation as follows

and tried calling up values but have hit a hurdle

AnalyteDecList <- c("Fe", "SiO2", "Al2O3", "TiO2", "Mn",'CaO')
decimlist <- data.frame(analytes = AnalyteDecList,
                        mean.dec = c(2,2,2,3,3,3), #decimal places for the mean 
                        sd.Dec = c(3,3,3,4,4,4)) #decimal places for SD

decimlist[decimlist$analytes == "Fe" %in% decimlist$analytes,] #get the decimal places for Fe

Am I even taking the right approach? any help on how to solve my problem is greatly appreciated

Make the function such that it displays decimal places dynamically.

LabSD <- function(x, sd.Dec) {
  lab.SD <- round(mapply(sd, x[-1], na.rm = T), digits = sd.Dec)
  SD.All <- unlist(x[-1]) #convert all the values to a vector
  lab.SD.T <- format(round(lab.SD ,sd.Dec),nsmall = sd.Dec)
  lab.SD.All <- round(sd(SD.All, na.rm = T), digits = sd.Dec)
  lab.SD.All.T <- format(round(lab.SD.All,sd.Dec),nsmall = sd.Dec)
  lab.SDSummary <- c(lab.SD.T, lab.SD.All.T)
  return(lab.SDSummary)
}

Pass it using Map :

decimlist$sd.Dec
#[1] 3 3 3 4 4 4


Map(LabSD, df[decimlist$analytes], decimlist$sd.Dec)

#$Fe
#      2       3       4       5       7       8      10      12         
#"0.355" "0.218" "0.080" "0.034" "0.125" "0.116" "0.176" "0.150" "0.210" 

#$SiO2
#      2       3       4       5       7       8      10      12         
#"0.033" "0.091" "0.079" "0.048" "0.060" "0.086" "0.111" "0.065" "0.097" 

#$Al2O3
#      2       3       4       5       7       8      10      12         
#"0.010" "0.010" "0.013" "0.012" "0.010" "0.017" "0.015" "0.049" "0.052" 

#$TiO2
#       2        3        4        5        7        8       10       12          
#"0.0000" "0.0000" "0.0000" "0.0000" "0.0052" "0.0042" "0.0000" "0.0031" "0.0055" 

#$Mn
#       2        3        4        5        7        8       10       12          
#"0.0096" "0.0056" "0.0103" "0.0105" "0.0149" "0.0092" "0.0082" "0.0175" "0.0132" 

#$CaO
#       2        3        4        5        7        8       10       12          
#"0.0052" "0.0041" "0.0052" "0.0052" "0.0041" "0.0015" "0.0000" "0.1030" "0.0392" 

You can use the same process for displaying mean.

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