Настроить нормализовать по группе в R - PullRequest
3 голосов
/ 21 апреля 2019

У меня есть фрейм данных, который выглядит следующим образом:

group1<-c(rep(1,12))
group2<-c(rep('Low',6), rep('High',6))
var  <-c(1:6,1:6)
var1  <-c(2:13)
var2  <-c(20:31)  
df1<-data.frame(group1,group2,var,var1,var2)
group1<-c(rep(2,12))
group2<-c(rep('Low',6), rep('High',6))
var  <-c(1:6,1:6)
var1  <-c(2:13)
var2  <-c(20:31)  
df2<-data.frame(group1,group2,var,var1,var2)

df<-rbind(df1,df2)

  group1 group2 var var1 var2
1       1    Low   1    2   20
2       1    Low   2    3   21
3       1    Low   3    4   22
4       1    Low   4    5   23
5       1    Low   5    6   24
6       1    Low   6    7   25
7       1   High   1    8   26
8       1   High   2    9   27
9       1   High   3   10   28
10      1   High   4   11   29
11      1   High   5   12   30
12      1   High   6   13   31
13      2    Low   1    2   20
14      2    Low   2    3   21
15      2    Low   3    4   22
16      2    Low   4    5   23
17      2    Low   5    6   24
18      2    Low   6    7   25
19      2   High   1    8   26
20      2   High   2    9   27
21      2   High   3   10   28
22      2   High   4   11   29
23      2   High   5   12   30
24      2   High   6   13   31

Я хочу нормализовать свои столбцы следующим образом.Для каждой комбинации group1 и group2 я хочу разделить столбцы var1 и var1 с их первым элементом.Это позволяет мне построить общую шкалу / индекс по интересующим колонкам.Например, глядя на комбинацию group1=1 и group2=low, соответствующие элементы var1 должны быть преобразованы в 2/2,3/2,4/2,5/2,6/2,7/2 соответственно, для комбинации group1=1 и group2=High должно быть 8/8,9/8,10/8,11/8,12/8,13/8 и так далее.

Я хочу выполнить вышеуказанные преобразования как для var1, так и для var2.Ожидаемый результат должен выглядеть следующим образом:

   group1 group2 var var1 var2 var1_tra var2_tra
1       1    Low   1    2   20    1.000 1.000000
2       1    Low   2    3   21    1.500 1.050000
3       1    Low   3    4   22    2.000 1.100000
4       1    Low   4    5   23    2.500 1.150000
5       1    Low   5    6   24    3.000 1.200000
6       1    Low   6    7   25    3.500 1.250000
7       1   High   1    8   26    1.000 1.000000
8       1   High   2    9   27    1.125 1.038462
9       1   High   3   10   28    1.250 1.076923
10      1   High   4   11   29    1.375 1.115385
11      1   High   5   12   30    1.500 1.153846
12      1   High   6   13   31    1.625 1.192308
13      2    Low   1    2   20    1.000 1.000000
14      2    Low   2    3   21    1.500 1.050000
15      2    Low   3    4   22    2.000 1.100000
16      2    Low   4    5   23    2.500 1.150000
17      2    Low   5    6   24    3.000 1.200000
18      2    Low   6    7   25    3.500 1.250000
19      2   High   1    8   26    1.000 1.000000
20      2   High   2    9   27    1.125 1.038462
21      2   High   3   10   28    1.250 1.076923
22      2   High   4   11   29    1.375 1.115385
23      2   High   5   12   30    1.500 1.153846
24      2   High   6   13   31    1.625 1.192308

ПРИМЕЧАНИЕ: Числа могут быть любыми, обычно положительными действительными числами, и поскольку мой массив данных действительно большой, я не могу знать заранее, что может бытьэлемент, с которым я хочу разделить, чтобы выполнить такие преобразования.

Ответы [ 2 ]

1 голос
/ 21 апреля 2019

После группировки по 'group1', 'group2', используйте mutate_at, чтобы выполнить деление столбцов, выбранных по значению first этого столбца

library(dplyr)
df %>%
   group_by(group1, group2) %>% 
   mutate_at(vars(var1, var2), list(tra = ~ ./first(.)))
# A tibble: 24 x 7
# Groups:   group1, group2 [4]
#   group1 group2   var  var1  var2 var1_tra var2_tra
#    <dbl> <fct>  <int> <int> <int>    <dbl>    <dbl>
# 1      1 Low        1     2    20     1        1   
# 2      1 Low        2     3    21     1.5      1.05
# 3      1 Low        3     4    22     2        1.1 
# 4      1 Low        4     5    23     2.5      1.15
# 5      1 Low        5     6    24     3        1.2 
# 6      1 Low        6     7    25     3.5      1.25
# 7      1 High       1     8    26     1        1   
# 8      1 High       2     9    27     1.12     1.04
# 9      1 High       3    10    28     1.25     1.08
#10      1 High       4    11    29     1.38     1.12
# … with 14 more rows

Или используя data.table

nm1 <- c("var1", "var2")
nm2 <- paste0(nm1, "_tra")
library(data.table)
setDT(df)[, (nm2) := lapply(.SD, function(x) x/first(x)), 
              by = .(group1, group2), .SDcols = nm1]
0 голосов
/ 22 апреля 2019

Также вы можете использовать из sqldf любит следующее:

result <- sqldf('select df.*, (df.var1 + 0.0) / scale.s_var1 as var1_tra, (df.var2 + 0.0) / scale.s_var2 as var2_tra
          from df join 
                  (select group1, group2, min(var1) as s_var1, min(var2) as s_var2 
                   from df
                   group by group1, group2) as scale 
                 on df.group1 = scale.group1 AND df.group2 = scale.group2 
          ')

В приведенном выше коде сначала мы находим минимальное значение для var1 и var2 для каждой группы, используя следующий запрос:

select group1, group2, min(var1) as s_var1, min(var2) as s_var2 
from df
group by group1, group2

И использовать это в качестве вложенного запроса и объединения с исходным фреймом данных df на равенство по значению group1 и group2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...