ha554an
ha554an

Reputation: 113

ggplot facet grid within a factor

Consider data that looks like this

fitem<-rep(rep(1:16,each=3),2)
fsubs<-factor(rep(rep(paste('sub',1:3,sep=''),16),2))
ftime<-factor(as.character(rep(c('a','b'),each=48)))
fcounts<-as.numeric(round(runif(96,1,10)))
fdf<-data.frame(fsubs,fitem,fcounts,ftime)


head(df)

  fsubs fitem fcounts ftime
1  sub1     1       8     a
2  sub2     1      10     a
3  sub3     1       4     a
4  sub1     2       4     a
5  sub2     2       1     a
6  sub3     2       6     a

I would like to plot a facet grid that shows the counts for the two time points ('a','b'), subject-wise. I can't seem to figure out how to plot this in ggplot

here is my ugly attempt to do it

fdf_counts<-data.frame()
for (i in unique(fdf$fsubs)){
  fdf_counts<-append(fdf_counts,cbind(fdf%>%filter(fsubs==i,ftime=='a')%>%dplyr::select(fcounts),
                        fdf%>%filter(fsubs==i,ftime=='b')%>%dplyr::select(fcounts)))

fdf_counts<-data.frame(fdf_counts)
}

s1<-ggplot(fdf_counts,aes(x=fcounts,y=fcounts.1))+geom_point()+geom_smooth(method='lm')+labs(x='a',y='b',title='sub1')
s2<-ggplot(fdf_counts,aes(x=fcounts.2,y=fcounts.3))+geom_point()+geom_smooth(method='lm')+labs(x='a',y='b',title='sub2')
s3<-ggplot(fdf_counts,aes(x=fcounts.4,y=fcounts.5))+geom_point()+geom_smooth(method='lm')+labs(x='a',y='b',title='sub3')



plot_grid(s1,s2,s3)#from 'cowplot' package

enter image description here

How can I do this with using the original fdf data.frame? Especially as the # of subs increase

Or for example if I wanted to plot one scatter plot across all of the subs with fcounts against eachother with ftime(a) as x axis and ftime(b) as y axis?

Upvotes: 1

Views: 494

Answers (3)

Daniel_j_iii
Daniel_j_iii

Reputation: 3252

Just tried to create a visualization that would analyze all 4 variables. Got a geom_histogram

```{r}
fitem<-rep(rep(1:16,each=3),2)
fsubs<-factor(rep(rep(paste('sub',1:3,sep=''),16),2))
ftime<-factor(as.character(rep(c('a','b'),each=48)))
fcounts<-as.numeric(round(runif(96,1,10)))
fdf<-data.frame(fsubs,fitem,fcounts,ftime)

fdf_counts<-data.frame()
for (i in unique(fdf$fsubs)){
  fdf_counts<-append(fdf_counts,cbind(fdf%>%filter(fsubs==i,ftime=='a')%>%dplyr::select(fcounts),
                        fdf%>%filter(fsubs==i,ftime=='b')%>%dplyr::select(fcounts)))

fdf_counts<-data.frame(fdf_counts)
}


ggplot(data = fdf, mapping = aes(x = fdf$fsubs, y = fdf$fcounts, fill = fdf$fitem)) +               geom_bar(stat = "identity", position =     "dodge") + facet_grid(cols = vars(ftime))


```

enter image description here

Upvotes: 0

Parfait
Parfait

Reputation: 107737

Consider a merge solution with data frame by itself on fsubs and fitem (being sequential number of items per fsubs and ftime grouping). This approach allows you to keep your long, tidy data format which is ideal format for ggplot since you can then facet_grid using fsubs without iteration.

mdf <- merge(subset(fdf, ftime=="a"), 
             subset(fdf, ftime=="b"), 
             by=c("fsubs", "fitem"), 
             suffixes=c("", "_"))

ggplot(mdf, aes(x=fcounts, y=fcounts_)) + 
  geom_point() + 
  geom_smooth(method='lm') +
  labs(x='a', y='b') + 
  facet_grid(~fsubs)

Plot Output

Upvotes: 1

Paul van Oppen
Paul van Oppen

Reputation: 1495

This should get you close:

library(dplyr)
library(tidyr)
library(tibble)
library(ggplot2)

fitem<-rep(rep(1:16,each=3),2)
fsubs<-factor(rep(rep(paste('sub',1:3,sep=''),16),2))
ftime<-factor(as.character(rep(c('a','b'),each=48)))
fcounts<-as.numeric(round(runif(96,1,10)))
fdf<-tibble(fsubs,fitem,fcounts,ftime)


fdf <- fdf %>%
  group_by(ftime) %>%
  mutate(row_id = row_number()) %>%
  pivot_wider(values_from = fcounts,
              names_from = ftime)


ggplot(data = fdf, aes(x = a, y = b)) +
  geom_point() +
  geom_smooth(method = "lm") +
  facet_wrap(fsubs ~ ., ncol = 1)

The tidyr function pivot_wider allows us to create the shape of the data we need without explicit loops: create new columns a and b with values from fcounts. We do need to create a unique row id to make this work.

By the way, when I run your code the plots look different from what you posted in the question.

With this output: enter image description here

Upvotes: 1

Related Questions