Создать новый столбец на основе соответствия регулярному выражению - PullRequest
1 голос
/ 27 мая 2020

Проблема

Я хотел бы создать новый столбец для относительного стандартного отклонения, используя следующую формулу: stdev * 100 / abs(mean). У меня более 40 переменных, каждая со своими stdev и mean (то есть 80 столбцов). Я хотел бы использовать регулярные выражения для вычисления относительного стандартного отклонения из двух столбцов (stdev и mean) на основе предыдущих имен. Например, для столбцов AceticAcid.stdev и AceticAcid.mean вычислите относительное стандартное отклонение, чтобы автоматически создать новый столбец AcetiAcid.rsd. Уравнение: AceticAcid.stdev * 100 / abs(AceticAcid.mean).


Пример фрейма данных

print(df)

  AceticAcid.mean AceticAcid.stdev Glucose.mean Glucose.stdev Propanol.mean Propanol.stdev
1        28.75775         0.911130     48.27333     4.4991249      144.4770       38.34122
2        78.83051        10.562110     28.13337     1.2304387      134.6402       31.76264
3        40.89769        17.848381     37.10283     0.2102977      132.0253       33.76568
4        88.30174        11.028700     32.90534     1.6396036      149.7135       21.56639
5        94.04673         9.132295     14.11699     4.7725182      132.7853       15.88455

Желаемый результат (не заботьтесь о порядке новых столбцов)

print(df_rsd)

  AceticAcid.mean AceticAcid.stdev Glucose.mean Glucose.stdev Propanol.mean Propanol.stdev AceticAcid.rsd Glucose.rsd Propanol.rsd
1        28.75775         0.911130     48.27333     4.4991249      144.4770       38.34122       3.168294   9.3201039     26.53795
2        78.83051        10.562110     28.13337     1.2304387      134.6402       31.76264      13.398504   4.3735921     23.59076
3        40.89769        17.848381     37.10283     0.2102977      132.0253       33.76568      43.641536   0.5667969     25.57515
4        88.30174        11.028700     32.90534     1.6396036      149.7135       21.56639      12.489788   4.9827894     14.40511
5        94.04673         9.132295     14.11699     4.7725182      132.7853       15.88455       9.710380  33.8069175     11.96258

Повторяющаяся попытка ... Я не хочу записывать их 40 раз (должен быть хороший способ регулярного выражения для достижения этого):

df_rsd <- df %>% mutate(AceticAcid.rsd = AceticAcid.stdev * 100 / abs(AceticAcid.mean),
                        Glucose.rsd = Glucose.stdev * 100 / abs(Glucose.mean),
                        Propanol.rsd = Propanol.stdev * 100 / abs(Propanol.mean))

Воспроизводимые данные

structure(list(AceticAcid.mean = c(28.7577520124614, 78.8305135443807, 
40.89769218117, 88.3017404004931, 94.0467284293845), AceticAcid.stdev = c(0.911129987798631, 
10.5621097609401, 17.8483808878809, 11.0287002893165, 9.13229470606893
), Glucose.mean = c(48.2733338139951, 28.1333662476391, 37.1028254181147, 
32.9053360782564, 14.1169873066247), Glucose.stdev = c(4.49912485200912, 
1.2304386717733, 0.210297667654231, 1.63960359641351, 4.77251824573614
), Propanol.mean = c(144.476965803187, 134.64017030783, 132.025340688415, 
149.713488831185, 132.785289955791), Propanol.stdev = c(38.3412187267095, 
31.7626409884542, 33.7656808178872, 21.5663894917816, 15.884545892477
)), class = "data.frame", row.names = c(NA, -5L))

Ответы [ 2 ]

2 голосов
/ 27 мая 2020

альтернатива, также с tidyverse.

library(tidyverse)

df_long <- df %>% 
  mutate(measurement_number=row_number(), .before=1) %>% 
  pivot_longer(cols=-measurement_number, names_to="var", values_to="value") %>% 
  separate(var, into=c("var", "indicator")) %>% 
  pivot_wider(id_cols=c("measurement_number", "var"), names_from = indicator, values_from=value) %>% 
  mutate(rsd=stdev * 100 / abs(mean)) %>% 
  arrange(var, measurement_number)

df_long
#> # A tibble: 15 x 5
#>    measurement_number var         mean  stdev    rsd
#>                 <int> <chr>      <dbl>  <dbl>  <dbl>
#>  1                  1 AceticAcid  28.8  0.911  3.17 
#>  2                  2 AceticAcid  78.8 10.6   13.4  
#>  3                  3 AceticAcid  40.9 17.8   43.6  
#>  4                  4 AceticAcid  88.3 11.0   12.5  
#>  5                  5 AceticAcid  94.0  9.13   9.71 
#>  6                  1 Glucose     48.3  4.50   9.32 
#>  7                  2 Glucose     28.1  1.23   4.37 
#>  8                  3 Glucose     37.1  0.210  0.567
#>  9                  4 Glucose     32.9  1.64   4.98 
#> 10                  5 Glucose     14.1  4.77  33.8  
#> 11                  1 Propanol   144.  38.3   26.5  
#> 12                  2 Propanol   135.  31.8   23.6  
#> 13                  3 Propanol   132.  33.8   25.6  
#> 14                  4 Propanol   150.  21.6   14.4  
#> 15                  5 Propanol   133.  15.9   12.0

df_wide <- df_long %>% 
  pivot_wider(id_cols=c("measurement_number"), 
              names_from = c(var), 
              values_from = c(mean, stdev, rsd),
              names_sep = ".")
df_wide
#> # A tibble: 5 x 10
#>   measurement_num~ mean.AceticAcid mean.Glucose mean.Propanol stdev.AceticAcid
#>              <int>           <dbl>        <dbl>         <dbl>            <dbl>
#> 1                1            28.8         48.3          144.            0.911
#> 2                2            78.8         28.1          135.           10.6  
#> 3                3            40.9         37.1          132.           17.8  
#> 4                4            88.3         32.9          150.           11.0  
#> 5                5            94.0         14.1          133.            9.13 
#> # ... with 5 more variables: stdev.Glucose <dbl>, stdev.Propanol <dbl>,
#> #   rsd.AceticAcid <dbl>, rsd.Glucose <dbl>, rsd.Propanol <dbl>

Создано 26.05.2020 с помощью пакета . (v0.3.0)

2 голосов
/ 27 мая 2020

Мы можем использовать split.default для разделения набора данных на list столбцов data.frame на основе удаления части суффикса в именах столбцов, затем l oop поверх list с lapply, выполните вычисление и назначьте его новому столбцу в 'df'

out <- lapply(split.default(df, sub("\\..*", "", names(df))), 
          function(x) x[[2]]* 100/abs(x[[1]]))
df[paste0(names(out), ".rsd")] <- out

df
#  AceticAcid.mean AceticAcid.stdev Glucose.mean Glucose.stdev Propanol.mean Propanol.stdev AceticAcid.rsd Glucose.rsd Propanol.rsd
#1        28.75775         0.911130     48.27333     4.4991249      144.4770       38.34122       3.168294   9.3201039     26.53795
#2        78.83051        10.562110     28.13337     1.2304387      134.6402       31.76264      13.398504   4.3735921     23.59076
#3        40.89769        17.848381     37.10283     0.2102977      132.0253       33.76568      43.641536   0.5667969     25.57515
#4        88.30174        11.028700     32.90534     1.6396036      149.7135       21.56639      12.489788   4.9827894     14.40511
#5        94.04673         9.132295     14.11699     4.7725182      132.7853       15.88455       9.710380  33.8069175     11.96258

Или с помощью tidyverse

library(purrr)
library(dplyr)
library(stringr)
df %>% 
  split.default(str_remove(names(.), "\\..*")) %>%
  map_dfc(~ .x[[2]] * 100/abs(.x[[1]])) %>% 
  rename_all(~ str_c(., '.rsd')) %>% 
  bind_cols(df, .)
...