R: объединить данные, чтобы свернуть 3 столбца в 1 столбец и удвоить это для каждой строки

#r #reshape2

#r #reshape2

Вопрос:

У меня есть данные, подобные следующим:

  df1
 id count white_v pink_v others_v 
 1  1     0.4      0.5   0.6
 1  2     0.5      0.5   0.747
 1  3     0.87     0.57  0.87
 2  1     1.5      2.5   1.2 
 ....
  

и я хочу изменить данные таким образом, чтобы они были совместимы с другим фреймом данных следующего формата:

  df2
  id count white pink
  1    1   1      0 
  1    1   0      1
  1    1   0      0
  1    1   1      0
  1    1   0      1
  1    1   0      0
  

итак, по сути, я хочу добавить значения pink, white, others из df1 в df2, но df2 отформатирован таким образом, что каждый цвет является фиктивным (0,0 как для розового, так и для белого означает, что столбец предназначен для других). И для каждой покупки каждого клиента в df2 есть 6 строк для этого, причем первые три строки являются повторением первых 3.

Чего я хочу добиться, так это фрейма данных, подобного следующему:

  df3
 id count white pink   v
  1  1    1     0      0.4 -> indicates the value of white_v for id 1,count1
  1  1    0     1      0.5 -> indicates the value of pink_v for id 1, count1
  1  1    0     0      0.6 -> indicates the value of others_v for id 1, count1
  1  1    1     0      0.4 -> indicates the value of white_v for id 1,count1
  1  1    0     1      0.5 -> similarly as above
  1  1    0     0      0.6  
  

Мне нужно перебрать каждого пользователя и количество покупок для них. Я думал об использовании циклов, но я застрял в том, как использовать i для индексации как строки df1, так и df2. Затем я также подумал об использовании reshape, но я не уверен, как я могу этого добиться.

Был бы очень признателен за любую информацию.

Комментарии:

1. На мой взгляд, это (форматирование df2) — плохая идея. Гораздо лучше иметь столбец с коэффициентом с «белым», «розовым» или «другим» в нем, а не с этими избыточными переменными 0/1.

Ответ №1:

С помощью tidyr и dplyr,

 library(tidyverse)

        # gather colors into long key and value columns
df1 %>% gather(color, v, white_v:others_v) %>% 
    # drop "_v" endings; use regex if you prefer
    separate(color, 'color', extra = 'drop') %>% 
    # add a vector of 1s to spread
    mutate(n = 1) %>%    # more robust: count(id, count, color, v)
    # spread labels and 1s to wide form
    spread(color, n, fill = 0)

##    id count     v others pink white
## 1   1     1 0.400      0    0     1
## 2   1     1 0.500      0    1     0
## 3   1     1 0.600      1    0     0
## 4   1     2 0.500      0    1     1
## 5   1     2 0.747      1    0     0
## 6   1     3 0.570      0    1     0
## 7   1     3 0.870      1    0     1
## 8   2     1 1.200      1    0     0
## 9   2     1 1.500      0    0     1
## 10  2     1 2.500      0    1     0
  

Комментарии:

1. но желаемый результат, который я хочу, заключается в том, что после того, как я получил первые три строки, я повторю три строки один раз, а затем продолжу .. формат df3 — это то, что я хочу

2. Повторять вручную, чтобы выровнять их, — очень, очень плохая идея. Вместо этого используйте соединение. Как упоминал Фрэнк, это, вероятно, проще в длинной форме.

3. Еще одна интересная альтернатива: df1 %>% gather(color, v, white_v:others_v) %>% model.matrix( ~ . - 1, data = .) %>% as.data.frame()