Pergunta

Eu quero ser capaz de summarize um agrupados quadro de dados, onde nem sempre eu sei de quais variáveis estarão presentes, mas eu sei como eu quero resumir cada variável, se ele estiver presente.

Vamos dizer que eu tenho uma dataframe como tal:

df <- data.frame(id = c(rep('a', 5), rep('b', 8), rep('c', 4)),
                 var1 = round(runif(17) * 10, 3),
                 var2 = sample(c(1:4), 17, replace = TRUE),
                 var4 = sample(1:1000, 17))
> df

   id  var1 var2 var4
1   a 5.930    4  360
2   a 7.265    2  713
3   a 3.704    3  117
4   a 5.149    2  782
5   a 3.777    2  640
6   b 4.183    2  802
7   b 0.107    2  638
8   b 5.323    4  327
9   b 4.322    2  631
10  b 0.937    3  921
11  b 5.558    2  570
12  b 5.902    4  363
13  b 0.671    3  432
14  c 0.475    1  845
15  c 1.562    3  620
16  c 4.464    2  997
17  c 1.714    2  714

Aviso var3 está faltando.Às vezes ele está lá, às vezes não é.É sempre o mesmo tipo quando ele está presente.Eu gostaria de ser capaz de ordenadamente manipular ambos os casos.

Digamos que, resumindo por id, Eu quero que a média de var1, a mediana de var2, a mediana de var3 (quando presente) e o máximo de var4.Se todas as variáveis estavam presentes eu poderia defini-lo assim:

library('dplyr')
set.seed(111)
result <- df %>% group_by(id) %>%
  summarize(var1 = mean(var1),
            var2 = median(var2),
            var3 = median(var3),
            var4 = max(var4))

No entanto, desde var3 não está lá, eu recebo um erro: Error in median(var3) : object 'var3' not found.

Intuitivamente, eu iria tentar algo como:

result <- df %>% group_by(id) %>%
  summarize(if('var1' %in% names(df)) var1 = mean(var1) else NULL,
            if('var2' %in% names(df)) var2 = median(var2) else NULL,
            if('var3' %in% names(df)) var3 = median(var3) else NULL,
            if('var4' %in% names(df)) var4 = max(var4) else NULL)

Mas, obviamente, não funciona, ou talvez a minha intuição é um pouco fora.

Alguém tem alguma sugestão de como eu poderia fazer isso de forma limpa usando dplyr?Como você pode imaginar, df na realidade é um grande quadro de dados com muitas colunas e var3 é um qualquer número de colunas que poderia estar faltando.

Foi útil?

Solução

Esta não é exatamente a solução, mas talvez uma solução, se você não quiser criar todos os possíveis colunas iniciais, como sugerido por @joran.Ele primeiro irá criar todas as colunas que você especificar, mas alguns deles só serão NA.Depois, você pode excluir as colunas utilizando aplicar.Note, porém, que o names(dd), quando usado dentro de dplyr cadeia, só reconhece os nomes das colunas que estavam na entrada de dados.quadro, não aqueles criados na mesma operação.

dd <- dd %>% 
  group_by(id) %>%
  summarize(var1 = ifelse("var1" %in% names(dd), mean(var1), NA),
            var2 = ifelse("var2" %in% names(dd), max(var2), NA))  

dd <- dd[,apply(dd, 2, function(x) ifelse(all(is.na(x)), FALSE, TRUE))]

Outra possível solução poderia estar usando o summarise_each função, mas eu acho que depende se você deseja, por exemplo, a média, mediana e máximo de todas as colunas ou não.

Outras dicas

Eu acho que você pode fazer isso em várias etapas:

  1. converter da gama a muito tempo usando melt
  2. resumir usando dplyr
  3. converter de tempo para utilização larga dcast

Por exemplo:

tmp <- melt(df, id.vars="id")

tmp <- tmp %>%
  group_by(id, variable) %>%
  summarise(mean = mean(value), median = median(value), max = max(value))

tmp <- melt(tmp, id.vars=c("id", "variable"), variable.name="stat")

tmp <- dcast(tmp, id ~ stat + variable)

Eu tive que adicionar mais um passo, porque você quer média, mediana e máximo para as diferentes variáveis.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top