R - Создать новые столбцы из вычисленных процентов с суммой данных в нескольких различных столбцах и строках - PullRequest
0 голосов
/ 23 октября 2018

Я хочу взять значения из столбца Su в data.frame df и создать новые столбцы с процентами от строки по отношению к соответствующим категориям во всех строках в Ca, Tr, 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

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

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

@ Решение 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 голосов
/ 23 октября 2018

A 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 
...