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

Итак, у меня есть процесс, для которого я сейчас использую Excel, и я хочу найти наиболее эффективный способ сделать это в R.

Мои данные принимают эту форму:

ID <- c(rep(1, 3), rep(2, 3))
Source <- rep(c("A", "A", "B"), 2)
Total <- c(11, 13, 12, 25, 27, 26)
Actions <- c(3, 2, 3, 8, 9, 10)
df <- data.frame(ID, Source, Total, Actions)
df 
#   ID Source Total Actions
# 1  1      A    11       3
# 2  1      A    13       2
# 3  1      B    12       3
# 4  2      A    25       8
# 5  2      A    27       9
# 6  2      B    26      10

Я запускаю агрегат на Total и Actions:

df2 <- aggregate(cbind(Total, Actions) ~ ID + Source, 
          data = df, FUN=sum)
df2
#   ID Source Total Actions
# 1  1      A    24       5
# 2  2      A    52      17
# 3  1      B    12       3
# 4  2      B    26      10

Но что я действительно хочу, так это ситуация, когда итоговые значения для A и итоговые значения для B являются отдельными столбцами в одной таблице. В настоящее время я делаю это так:

df2_A <- df2[(df2$Source == "A"), ]
df2_B <- df2[(df2$Source == "B"), ]
x <- merge(df2_A, df2_B, by.x = "ID", by.y = "ID")
x 
#   ID Source.x Total.x Actions.x Source.y Total.y Actions.y
# 1  1        A      24         5        B      12         3
# 2  2        A      52        17        B      26        10   

У меня вопрос: есть ли более элегантный способ перейти от df до x за один шаг? Я чувствую, что то, что я делаю сейчас, - грубый хак, и я хочу расширить свои знания R.

Ответы [ 3 ]

0 голосов
/ 03 мая 2018

A reshape2 версия:

library(reshape2)

> dcast(melt(df, id.vars = ID), ID ~ Source + variable, fun.aggregate = sum)
  ID A_Total A_Actions B_Total B_Actions
1  1      24         5      12         3
2  2      52        17      26        10

И некая сомнительная базовая версия, которая приближает вас к желаемому результату, включая соответствующие исходные столбцы:

do.call(rbind, lapply(split(df, f = ID), function(x) {
  y <- (split(x, Source))
  ID = x[[1]][1]
  cbind(ID, do.call(cbind, lapply(y, function(z) { 
    w <- data.frame(Source = z[1,2])
    q <- data.frame(t(colSums(z[,c("Total", "Actions")])))
    data.frame(w,q)
  })))
}))

  ID A.Source A.Total A.Actions B.Source B.Total B.Actions
1  1        A      24         5        B      12         3
2  2        A      52        17        B      26        10
0 голосов
/ 03 мая 2018

ОП довольно близок к решению. Ему нужно просто взять еще одну совокупность сверх df2, и он бы получил ответ.

Короче говоря aggregate из aggregate - это вариант для поиска решения:

aggregate(cbind(Source,Total,Actions)~ID, 
  data=aggregate(cbind(Total, Actions) ~ ID + Source, data = df, FUN=sum), I)
#   ID Source.1 Source.2 Total.1 Total.2 Actions.1 Actions.2
# 1  1        1        2      24      12         5         3
# 2  2        1        2      52      26        17        10
0 голосов
/ 02 мая 2018

Возможно, вы захотите упростить всю операцию в одну трубу

library(dplyr)
library(tidyr)
df %>% group_by(ID, Source) %>% 
  summarize_all(sum) %>% ungroup()%>%
  gather(key, value, -c(ID, Source)) %>% 
  unite(newkey, key, Source) %>% 
  spread(newkey, value)
#> # A tibble: 2 x 5
#>      ID Actions_A Actions_B Total_A Total_B
#> * <dbl>     <dbl>     <dbl>   <dbl>   <dbl>
#> 1     1         5         3      24      12
#> 2     2        17        10      52      26
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...