Разделите значение строки на агрегированную сумму в R данных.фрейм

#r #dataframe

#r

Вопрос:

У меня есть следующий фрейм данных

 dat <- data.frame(x=c(1,2,3,3,2,1), y=c(3,4,4,5,2,5))
 

Теперь я хотел бы получить третий столбец, разделяющий значение строки y на агрегированные значения y (на основе уникальных значений в столбце x). Итак, тогда я получаю строку 1 следующим образом: 1,3,0.375; 0,375 вычисляется как 3 / (5 3).

Я относительно новичок в R и надеюсь, что вы сможете мне помочь. Спасибо!

Ответ №1:

Существуют различные способы решения этой проблемы, вот один

 with(dat, ave(y, x, FUN = function(x) x/sum(x)))
## [1] 0.3750000 0.6666667 0.4444444 0.5555556 0.3333333 0.6250000
 

Вот еще одна возможность

 library(data.table)
setDT(dat)[, z := y/sum(y), by = x]
dat
#    x y         z
# 1: 1 3 0.3750000
# 2: 2 4 0.6666667
# 3: 3 4 0.4444444
# 4: 3 5 0.5555556
# 5: 2 2 0.3333333
# 6: 1 5 0.6250000
 

Вот третий

 library(dplyr)
dat %>%
  group_by(x) %>%
  mutate(z = y/sum(y))

# Source: local data frame [6 x 3]
# Groups: x
# 
#   x y         z
# 1 1 3 0.3750000
# 2 2 4 0.6666667
# 3 3 4 0.4444444
# 4 3 5 0.5555556
# 5 2 2 0.3333333
# 6 1 5 0.6250000
 

Комментарии:

1. with(dat,y/ ave(y,x, FUN=sum)) было бы немного компактнее. Еще один вариант dat$y/xtabs(y~x, dat)[dat$x]

2. Итак dplyr , sum суммы по группам, созданным предыдущим group_by . Попробуйте с dat <- data.frame(x=c(1,1,4,4,5,5,6,6), y=c(5,6,1,0,3,1,2,3)) помощью then dat %>% group_by(x) %>% group_by(y) %>% mutate(w = y/sum(x)) , чтобы увидеть, что group_by(x) это не имеет никакого эффекта. И наоборот, не группировка обрабатывает весь фрейм данных как группу: dat %>% mutate(w = y/sum(x)) вычисляет относительные веса, суммируя до 1. Или dat %>% mutate(rel_x = x/sum(x)) %>% summarize(total = sum(rel_x)) выдает 1, как и должно быть.

3. @DavidTonhofer Что вам нужно?

4. @DavidArenburg Спасибо, Дэвид, мне понятно, что такое сумма по группам, я просто хотел написать заметку о том, что я тестировал.

Ответ №2:

Вот некоторые базовые решения R.:

1) prop.table Использует базовую prop.table функцию ave следующим образом:

 transform(dat, z = ave(y, x, FUN = prop.table))
 

предоставление:

   x y         z
1 1 3 0.3750000
2 2 4 0.6666667
3 3 4 0.4444444
4 3 5 0.5555556
5 2 2 0.3333333
6 1 5 0.6250000
 

2) суммируйте Это также работает:

 transform(dat, z = y / ave(y, x, FUN = sum))
 

Ответ №3:

И, конечно, есть способ для людей, думающих на SQL, в данном случае очень многословный, но хорошо обобщающий все виды других подобных проблем:

 library(sqldf)
dat <- sqldf("
  with sums as (
    select
      x
      ,sum(y) as sy
    from dat
    group by x
  )
  select
    d.x
    ,d.y
    ,d.y/s.sy as z
  from dat d
  inner join sums s
    on d.x = s.x
")