#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()