Reputation: 4243
I have a dataframe below:
dat
Day Col1 Another Value High/Low
2018-01-01 A B 20 High
2018-01-01 B G 30 High
2018-01-02 C D 40 Low
2018-01-02 C M 70 Low
2018-01-02 C G 50 Low
How do I reformat this so that it looks like this:
I want to order the reasons also in descending order if it's high and ascending if low. Also each date will never have multiple high/lows.
Day Reason_1 Value_1 Reason_2 Value_2 Reason_3 Value_3
2018-01-01 B-G 30 A-B 20 NA NA
2018-01-02 C-D 40 C-G 50 C-M 70
I tried to use the spread function but that makes the Col1 and Another values as columns:
library(tidyr)
new_df<- spread(dat, Col1_Another_Combined, Value)
No luck with this though
Upvotes: 0
Views: 37
Reputation: 10761
We can use a variety of verbs from the tidyverse
:
First, we group by day, and then calculate a ranking of the Value
. We use row_number
, because it will result in a unique ranking across the rows. We use unite
to create the reason
column, and then use gather
, unite
, and spread
to do the final wide-to-long-to-wide transformation. One thing to note is that the value_*
columns are still coded as character values, which can be easily changed.
dat %>%
group_by(Day) %>%
mutate(row_num_value = row_number(Value)) %>% # ranking
unite(reason, Col1, Another, sep = " - ") %>% # reason column
gather(variable, value, reason, Value) %>% # convert to long
unite(variable2, variable, row_num_value, sep = '_') %>%
spread(variable2, value) # convert to wide
# A tibble: 2 x 8
# Groups: Day [2]
Day High.Low reason_1 reason_2 reason_3 Value_1 Value_2 Value_3
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 2018-01-01 High A - B B - G NA 20 30 NA
2 2018-01-02 Low C - D C - G C - M 40 50 70
Upvotes: 2