Подтвердить что ты не робот

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

У меня есть длинный набор данных, который я хотел бы сделать широким, и мне любопытно, есть ли способ сделать это всего за один шаг, используя пакеты 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 одним выстрелом, одновременно обрабатывая переменные "транзакции" и "сумма"? И в идеале с новыми более подходящими именами столбцов?

4b9b3361

Ответ 1

В "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

Вы также можете использовать базу R 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

Ответ 2

С data.table v1.9.6 + мы можем одновременно использовать несколько столбцов value.var (а также использовать несколько функций агрегации в fun.aggregate). Подробнее см. ?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