Я хочу взять значения из столбца Su в data.frame df и создать новые столбцы с процентами из строки по отношению к соответствующим категориям во всех строках в Ca, {{X3 }}, Sa и ST

Чтобы перейти от этого:

Ca Sa ST Tr Su A T1 S cn 3.2 A T2 S ct 1.7 C T1 S sn 2.1 H T3 R ct 1.4

К этому:

Ca Sa ST Tr Su p_Sa p_ST p_Tr p_Ca A T1 S cn 3.2 60.4 45.7 100.0 65.3 A T2 S ct 1.7 100.0 24.2 54.8 34.7 C T1 S sn 2.1 39.6 30.0 100.0 100.0 H T3 R ct 1.4 100.0 100.0 45.2 100.0

Где p_Sa рассчитывается как 100 * (значение Su) / (сумма всех строк, которые имеют одинаковый образец в столбце Sa), или - для первой записи: (100 * (3.2 / (3.2 + 2.1))); p_ST = 100 * (значение Su) / (сумма всех строк, которые имеют одинаковый образец в столбце ST) и так далее и так далее

Я пробовал использовать ddply(df, .(Sa), transform, perc.Sa=Su/sum(Su)) но я думаю, что могу использовать его неправильно и получить эту ошибку на моем фактическом df, который имеет гораздо больше строк и несколько дополнительных столбцов, чем в примере выше:

Error: Column indexes must be at most 10 if positive, not 17, 35, 64, 79, 108, 128, 145, 173, 189, 230, 244, 255, 296, 310, 337, 353, 374, 408, 418, 441, 477, 493, 525, 551

Большое спасибо за любую помощь.

0
learning5023 23 Окт 2018 в 23:29

2 ответа

Лучший ответ

Решением dplyr было бы group_by каждого из столбцов.

library(dplyr)
df %>% group_by(Sa) %>% mutate(p_Sa = 100*Su/(sum(Su))) %>% ungroup %>%
  group_by(ST) %>%  mutate(p_ST = 100*Su/(sum(Su))) %>% ungroup %>%  
  group_by(Tr) %>%  mutate(p_Tr = 100*Su/(sum(Su))) %>% ungroup %>% 
  group_by(Ca) %>%  mutate(p_Ca = 100*Su/(sum(Su)))


# A tibble: 4 x 9
# Groups:   Ca [3]
#   Ca    Sa    ST    Tr       Su  p_Sa  p_ST  p_Tr  p_Ca
#   <fct> <fct> <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 A     T1    S     cn      3.2  60.4  45.7 100    65.3
# 2 A     T2    S     ct      1.7 100    24.3  54.8  34.7
# 3 C     T1    S     sn      2.1  39.6  30   100   100  
# 4 H     T3    R     ct      1.4 100   100    45.2 100 
0
jasbner 23 Окт 2018 в 20:35

Решение @jasbner полностью работает, однако вот более автоматизированное решение:

library(tidyverse)
library(reshape2)

df %>%
  rowid_to_column() %>%
  gather(var, val, -Su, -rowid) %>% 
  group_by(val) %>% 
  mutate(res = 100*Su/(sum(Su)),
         var2 = paste("p_", var, sep = "")) %>% 
  ungroup() %>% 
  dcast(rowid~var2, first, value.var = "res") %>% 
  right_join(df %>% rowid_to_column(), by = c("rowid" = "rowid")) %>% 
  select(-rowid)

        p_Ca      p_ST      p_Sa      p_Tr Ca Sa ST Tr  Su
1  65.30612  45.71429  60.37736 100.00000  A T1  S cn 3.2
2  34.69388  24.28571 100.00000  54.83871  A T2  S ct 1.7
3 100.00000  30.00000  39.62264 100.00000  C T1  S sn 2.1
4 100.00000 100.00000 100.00000  45.16129  H T3  R ct 1.4
0
tmfmnk 23 Окт 2018 в 21:35
52957394