0
votes

Remodeler la trame de données R (calculer la moyenne d'une colonne en fonction de plusieurs colonnes de `` niveau '')

J'ai un dataframe R avec ce type de structure (exemple factice):

spread_df_C <- spread(df, B, C)
aggregated_df_C <- aggregate(spread_df$a, list(spread_df$A), mean)

spread_df_D <- spread(df, B, D)
aggregated_df_D <- aggregate(spread_df$a, list(spread_df$A), mean)

new_df <- merge(aggregated_df_C, aggregated_df_D, by=c("A", "A")

"A", "B", "C" et "D" sont des en-têtes de colonne.

/ p>

Je veux remodeler ce dataframe de sorte que j'obtienne la moyenne (moyenne) de "C" et "D" par chaque niveau de "A" et "B".

Donc le produit final que je veux serait:

new_df

A BaC BbC BaD BbD 
1  4   2   4   8
2  5   4   6   3

J'ai réussi à le faire d'une manière très grossière:

df 

A B C D
1 a 3 5
1 a 5 3
1 b 2 8
2 a 4 7
2 a 6 5
2 b 4 3

...

Cela me donnerait finalement le produit final, mais je calcule laborieusement la moyenne pour chacun des niveaux. Je dois faire cela pour plusieurs niveaux, et il doit y avoir une manière plus élégante de l'exécuter.

Experts, veuillez aider


0 commentaires

3 Réponses :


1
votes

Une option utilisant le package reshape2 .

library(reshape2)
dcast(melt(dat, measure.vars = c("C", "D")), A ~ B + variable, fun.aggregate = mean)
#  A a_C a_D b_C b_D
#1 1   4   4   2   8
#2 2   5   6   4   3

La première étape consiste à fondre les colonnes C et D , puis reconstituer la trame de données résultante au format large.


0 commentaires

0
votes

Avec tidyverse , vous pouvez faire:

df %>%
 gather(var, val, -c(1:2)) %>%
 group_by_at(1:3) %>%
 summarise(val = mean(val)) %>%
 ungroup() %>%
 mutate(var = paste(var, B, sep = "_")) %>%
 select(-2) %>%
 spread(var, val)

      A   C_a   C_b   D_a   D_b
  <int> <dbl> <dbl> <dbl> <dbl>
1     1     4     2     4     8
2     2     5     4     6     3


0 commentaires

1
votes

Considérez le remodelage de la base R après l'agrégation et le changement de nom de colonne avant / après la période:

agg <- aggregate(. ~ A + B, df, mean)
rdf <- reshape(agg, idvar = "A", timevar = "B",  direction = "wide")

names(rdf)[-1] <- paste0("B", substr(names(rdf)[-1], 3, 3), substr(names(rdf)[-1], 1, 1))

rdf
#   A BaC BaD BbC BbD
# 1 1   4   4   2   8
# 2 2   5   6   4   3


0 commentaires