This is problem set #2, in which we hope you will practice the packages tidyr and dplyr. Along with the tutorial we used in class, there are some great cheat sheets from RStudio.

The data set

This data set comes from a replication of Janiszewski and Uy (2008), who investigated whether the precision of the anchor for a price influences the amount of adjustment. (We use these data briefly in the tutorial).

In the data frame, the Input.condition variable represents the experimental condition (under the rounded anchor, the rounded anchor, over the rounded anchor). Input.price1, Input.price2, and Input.price3 are the anchors for the Answer.dog_cost, Answer.plasma_cost, and Answer.sushi_cost items.

Part 1: Making these data tidy

Load the tidyverse package and the data

library(tidyverse)
## Loading tidyverse: ggplot2
## Loading tidyverse: tibble
## Loading tidyverse: tidyr
## Loading tidyverse: readr
## Loading tidyverse: purrr
## Loading tidyverse: dplyr
## Conflicts with tidy packages ----------------------------------------------
## filter(): dplyr, stats
## lag():    dplyr, stats
d <- read.csv("data/janiszewski_rep_cleaned.csv")

This data frame is in wide format - that means that each row is a participant and there are multiple observations per participant. This data is not tidy.

To make this data tidy, we’ll do some cleanup. First, remove the columns you don’t need, using the verb select.

HINT: ?select and the examples of helper functions will help you be efficient.

d.tidy <- select(d, WorkerId, Input.condition, Input.price1, Input.price2, Input.price3, Answer.dog_cost, Answer.plasma_cost, Answer.sushi_cost)

Try renaming some variables using rename. A good naming scheme is:

Try using the %>% operator as well. So you will be “piping” d %>% rename(...).

d.tidy <- d.tidy %>%
rename(id_number = WorkerId, condition = Input.condition, price_1 = Input.price1, price_2 = Input.price2, price_3 = Input.price3, dog_cost = Answer.dog_cost, plasma_cost = Answer.plasma_cost, sushi_cost = Answer.sushi_cost)

OK, now for the tricky part. Use the verb gather to turn this into a tidy data frame.

HINT: look for online examples!

d.tidy2 <- d.tidy %>%
  gather(answer, cost, dog_cost:sushi_cost)

Now spread these data back into a wide format data frame.

d.wide <- d.tidy2 %>%
  spread(answer, cost)

Part 2: Manipulating the data

NOTE: If you generally use plyr package, note that they do not play nicely together so things like the rename function won’t work unless you load dplyr after plyr.

As we said in class, a good thing to do is always to check histograms of the response variable. Do that now, using either regular base graphics (hist) or ggplot. What can you conclude?

library(ggplot2)
library(reshape2)
## 
## Attaching package: 'reshape2'
## The following object is masked from 'package:tidyr':
## 
##     smiths
ggplot(d.tidy2, aes(cost, fill=answer)) +
  geom_histogram(binwidth=500, position="dodge")
## Warning: Removed 1 rows containing non-finite values (stat_bin).

#The scale of the response variable (cost) is dependent upon the answer items. Therefore, not much can be drawn from this visualization, other than the scales for the three outcome variables are quite different. Sushi costs are around 20x smaller than than dog costs and 40x smaller than plasma costs. This will make visualizing data difficult. To be able to compare these different items, we will need to break it down using the filter and group verbs in dplyr.

OK, now we turn to the actual data anlysis. We’ll be using dplyr verbs to filter, group,mutate, and summarise the data.

Start by using summarise to compute the grand mean bet. (Note that this is the same as taking the grant mean - the value will come later. Right now we’re just learning the syntax of that verb.)

#I suppose this means you want the mean cost response for all subjects across all response items? I dont really see how this is useful and I'm not sure what the term 'grand mean bet' refers to.

d.tidy2 %>%
  summarise(avg_cost = mean(cost, na.rm=TRUE))
##   avg_cost
## 1 2022.557

This is a great time to get comfortable with the %>% operator. In brief, %>% allows you to pipe data from one function to another. So if you would have written:

d <- function(d, other_stuff)

you can now write:

d <- d %>% function(other_stufF)

That doesn’t seem like much, but it’s cool when you can replace:

d <- function1(d, other_stuff) d <- function2(d, lots_of_other_stuff, more_stuff) d <- function3(d, yet_more_stuff)

with

d <- d %>% function1(other_stuff) %>% function2(lots_of_other_stuff, more_stuff) %>% function3(yet_more_stuff)

In other words, you get to make a clean list of the things you want to do and chain them together without a lot of intermediate assignments.

Let’s use that capacity to combine summarise with group_by, which allows us to break up our summary into groups. Try grouping by item and condition and taking means using summarise, chaining these two verbs with %>%.

average_costs <-d.tidy2 %>%
  group_by(condition, answer) %>%
  summarise(avg_cost=mean(cost, na.rm=TRUE))


melt_costs <- melt(average_costs)
## Using condition, answer as id variables
ggplot(data=melt_costs, aes(x=condition, y=value, fill=condition)) + 
 geom_bar(stat="identity", position="dodge") +
  facet_wrap(~answer, scales="free_y")

Now we can see the mean cost for each of the three response categories (dog, plasma, sushi) within each of the three experimental conditions (over, rounded, under). There appear to be condition differences, but it’s difficult to tell the direction or significance of these differences. It doesnt appear that the rounded condition yeilds higher cost responses.

How are we going to plot condition differences? They are fundamentally different magnitudes from one another. Really we need the size of the deviation from the anchor, which means we need the anchor value. Let’s go back to the data and add that in.

Take a look at these two complex piped expression.s You don’t have to modify it, but see what is being done here with gather, separate and spread. Run each part (e.g. the first verb, the first two verbs, etc.) and after doing each, look at head(d.tidy) to see what they do.

# clean up 
d.tidy <- d %>% 
  select(WorkerId, Input.condition, 
         starts_with("Answer"), 
         starts_with("Input")) %>%
  rename(workerid = WorkerId,
         condition = Input.condition,          
         plasma_anchor = Input.price1,
         dog_anchor = Input.price2,
         sushi_anchor = Input.price3,
         dog_cost = Answer.dog_cost,
         plasma_cost = Answer.plasma_cost, 
         sushi_cost = Answer.sushi_cost) 
head(d.tidy)
##   workerid condition dog_cost plasma_cost sushi_cost plasma_anchor
## 1        1      over     2300        4800        8.7          5012
## 2        2      over     2450        4850        9.0          5012
## 3        3      over      800        1200        8.0          5012
## 4        4      over     2000        4200        9.0          5012
## 5        5      over     2000        4500        8.5          5012
## 6        6      over     1600        4600        8.0          5012
##   dog_anchor sushi_anchor
## 1       2508         9.36
## 2       2508         9.36
## 3       2508         9.36
## 4       2508         9.36
## 5       2508         9.36
## 6       2508         9.36
# now do the gathering and spreading
d.tidy <- d.tidy %>%
  gather(name, cost, 
         dog_anchor, plasma_anchor, sushi_anchor, 
         dog_cost, plasma_cost, sushi_cost) %>%
  separate(name, c("item", "type"), "_") %>%
  spread(type, cost) 

head(d.tidy)
##   workerid condition   item  anchor   cost
## 1        1      over    dog 2508.00 2300.0
## 2        1      over plasma 5012.00 4800.0
## 3        1      over  sushi    9.36    8.7
## 4        2      over    dog 2508.00 2450.0
## 5        2      over plasma 5012.00 4850.0
## 6        2      over  sushi    9.36    9.0

Now we can do the same thing as before but look at the relative difference between anchor and estimate. Let’s do this two ways:

To do the first, use the mutate verb to add a percent change column, then comute the same summary as before.

pcts <- d.tidy %>% 
  mutate(pct_change = ((anchor-cost)/anchor)*100) %>%
  group_by(condition, item) %>%
  summarise(avg_pct_change=mean(pct_change, na.rm=TRUE))

To do the second, you will need to group once by item, then to ungroup and do the same thing as before. NOTE: you can use group_by(…, add=FALSE) to set new grouping levels, also.

HINT: scale(x) returns a complicated data structure that doesn’t play nicely with dplyr. try scale(x)[,1] to get what you need.

z.scores <- d.tidy %>%
  mutate(z_score = scale(cost)[,1]) %>%
  group_by(condition, item) %>%
  summarise(avg_z_score=mean(z_score, na.rm=TRUE))

OK, now here comes the end: we’re going to plot the differences and see if anything happened. First the percent change:

ggplot(data=pcts, aes(x=item, y=avg_pct_change, fill=condition)) + geom_bar(stat="identity", position="dodge")

and the \(z\)-scores:

ggplot(data=z.scores, aes(x=item, y=avg_z_score, fill=condition)) + geom_bar(stat="identity", position="dodge")

What do you you see in this replication?

The original study concluded that a precise anchor results in less adjustment than a rounded anchor. The results of this replication do not appear to support this conclusion. Visualizing the average percent change in valuation across three items (dog, plasma, sushi) does not show a trend toward less adjustment when the anchor is precise (the over or under condition) or greater adjustment when the anchor is rounded.

===