суммирование строк на основе row.names и условия в col.names — R

#r #dataframe #sum

#r #dataframe #сумма

Вопрос:

 df <- data.frame(row.names = c('1s.u1','1s.u2','2s.u1','2s.u2','6s.u1'),fjri_deu_klcea= c('0','0','0','15','23'),hfue_klcea=c('2','2','0','156','45'),dji_dhi_ghcea_jk=c('456','0','0','15','15'),jdi_jdi_ghcea=c('1','2','3','4','100'),gz7_jfu_dcea_jdi=c('5','6','3','7','56'))

df
      fjri_deu_klcea hfue_klcea dji_dhi_ghcea_jk jdi_jdi_ghcea gz7_jfu_dcea_jdi
1s.u1              0          2              456             1                5
1s.u2              0          2                0             2                6
2s.u1              0          0                0             3                3
2s.u2             15        156               15             4                7
6s.u1             23         45               15           100               56
  

Я хочу суммировать df на основе cea части имен столбцов. Таким образом, все строки с одной и той же cea частью должны суммироваться.
df должно выглядеть так

         klcea      ghcea            dcea
1s.u1      2         457               5
1s.u2      2          2                6
2s.u1      0          3                3
2s.u2      171        19               7
6s.u1      68         115              56
  

Я подумал о том, чтобы сначала получить новый столбец с cea вызываемым именем cea , а затем суммировать его на основе row.names и соответственно cea
с чем-то вроде with(df, ave(cea, row.names(df), FUN = sum))

Я не знаю, как сгенерировать новый столбец на основе шаблона в строке. Я думаю grepl , это полезно, но я не мог что-то придумать, я попробовал df$cea <- df[grepl(colnames(df),'cea'),] , что неправильно…

Ответ №1:

Используя базовый R, вы можете извлечь часть «cea» из имени и использовать ее split.default для разделения фрейма данных на столбцы, которые затем можно использовать rowSums для суммирования каждого отдельного фрейма данных.

 sapply(split.default(df, sub('.*_(.*cea).*', '\1', names(df))), rowSums)

#      dcea ghcea klcea
#1s.u1    5   457     2
#1s.u2    6     2     2
#2s.u1    3     3     0
#2s.u2    7    19   171
#6s.u1   56   115    68
  

где sub часть возвращает :

 sub('.*_(.*cea).*', '\1', names(df))
#[1] "klcea" "klcea" "ghcea" "ghcea" "dcea" 
  

Ответ №2:

Использование dplyr:

 > df %>% rowwise() %>% mutate(klcea = sum(c_across(ends_with('klcea'))), 
                              ghcea = sum(c_across(contains('ghcea'))),
                              dcea = sum(c_across(contains('dcea')))) %>% 
                      select(klcea, ghcea, dcea)
# A tibble: 5 x 3
# Rowwise: 
  klcea ghcea  dcea
  <dbl> <dbl> <dbl>
1     2   457     5
2     2     2     6
3     0     3     3
4   171    19     7
5    68   115    56
  

Если вы хотите сохранить имена строк:

 > df %>% rownames_to_column('rn') %>% rowwise() %>% mutate(klcea = sum(c_across(ends_with('klcea'))), 
                              ghcea = sum(c_across(contains('ghcea'))),
                              dcea = sum(c_across(contains('dcea')))) %>% 
                      select(klcea, ghcea, dcea, rn) %>% column_to_rownames('rn')
      klcea ghcea dcea
1s.u1     2   457    5
1s.u2     2     2    6
2s.u1     0     3    3
2s.u2   171    19    7
6s.u1    68   115   56
>