Изменить несколько значений сразу

У меня длинный dataset, который я хотел бы сделать широким, и мне любопытно, есть ли способ сделать это всего за один шаг, используя пакеты reshape2 или tidyr в R.

Кадр данных df выглядит так:

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

Я бы хотел:

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

Я знаю, что могу получить часть пути с помощью reshape2 через, например:

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

Но есть ли способ переформатировать весь df одним выстрелом, который сразу обращается к переменным «транзакции» и «сумма»? И в идеале с новыми более подходящими именами столбцов?

В «reshape2» вы можете использовать recast (хотя, по моему опыту, это не широко известная функция).

 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 

Вы также можете использовать base R’s reshape :

 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 

Или, вы можете melt и dcast , как это (здесь с «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 

В более поздних версиях dcast.data.table из «data.table» (1.9.8) вы сможете сделать это напрямую . Если я правильно понимаю, что @Arun пытается реализовать, он будет выполнять преобразование без предварительного melt данных, что в настоящее время происходит с recast , что по существу является оберткой для последовательности операций melt + dcast .


И, для тщательности, вот 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 

С data.table v1.9.6 + мы можем одновременно использовать несколько столбцов value.var (а также использовать несколько функций агрегации в fun.aggregate ). ?dcast см. В разделе « ?dcast а также раздел «Примеры».

 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 
Давайте будем гением компьютера.