Remodele vários valores de uma só vez

Eu tenho um longo dataset que eu gostaria de fazer ampla e estou curioso para saber se há uma maneira de fazer isso tudo em uma única etapa usando os pacotes reshape2 ou tidyr em R.

O frame de dados df parece com isso:

 id type transactions amount 20 income 20 100 20 expense 25 95 30 income 50 300 30 expense 45 250 

Eu gostaria de chegar a isso:

 id income_transactions expense_transactions income_amount expense_amount 20 20 25 100 95 30 50 45 300 250 

Eu sei que posso fazer parte do caminho com o reshape2 via, por exemplo:

 dcast(df, id ~ type, value.var="transactions") 

Mas existe uma maneira de reformular o df inteiro de uma só vez, abordando as variables ​​”transactions” e “quantidade” de uma só vez? E idealmente com novos nomes de coluna mais apropriados?

Em “reshape2”, você pode usar a recast (embora, na minha experiência, essa não seja uma function amplamente conhecida).

 library(reshape2) recast(mydf, id ~ variable + type, id.var = c("id", "type")) # id transactions_expense transactions_income amount_expense amount_income # 1 20 25 20 95 100 # 2 30 45 50 250 300 

Você também pode usar a reshape da base R:

 reshape(mydf, direction = "wide", idvar = "id", timevar = "type") # id transactions.income amount.income transactions.expense amount.expense # 1 20 20 100 25 95 # 3 30 50 300 45 250 

Ou você pode melt e dcast , como este (aqui com “data.table”):

 library(data.table) library(reshape2) dcast.data.table(melt(as.data.table(mydf), id.vars = c("id", "type")), id ~ variable + type, value.var = "value") # id transactions_expense transactions_income amount_expense amount_income # 1: 20 25 20 95 100 # 2: 30 45 50 250 300 

Em versões posteriores do dcast.data.table do “data.table” (1.9.8) você será capaz de fazer isso diretamente . Se eu entendi corretamente, o que @Arun está tentando implementar seria fazer a reformulação sem primeiro ter que melt os dados, que é o que acontece atualmente com a recast , que é essencialmente um wrapper para uma sequência de operações de melt + dcast .


E, para ser minucioso, aqui está a abordagem tidyr :

 library(dplyr) library(tidyr) mydf %>% gather(var, val, transactions:amount) %>% unite(var2, type, var) %>% spread(var2, val) # id expense_amount expense_transactions income_amount income_transactions # 1 20 95 25 100 20 # 2 30 250 45 300 50 

Com data.table v1.9.6 +, podemos lançar várias colunas value.var simultaneamente (e também usar várias funções de agregação em fun.aggregate ). Por favor, veja ?dcast para mais e também a seção de exemplos.

 require(data.table) # v1.9.6+ dcast(dt, id ~ type, value.var=names(dt)[3:4]) # id transactions_expense transactions_income amount_expense amount_income # 1: 20 25 20 95 100 # 2: 30 45 50 250 300