Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R plot vary line thickness by frequency

Tags:

plot

r

ggplot2

Updated: Found a crude solution that is specific to the plot() function in R, but it would benefit from a much nicer plot. Any ideas? This is another level of plotting, but potentially, the transitions towards increased thickness could be gradual.

I have a simple data frame in R.

dft <- data.frame(line=c(rep("X1",4),rep("X2",4),rep("X3",4)),+ 
       time=rep(c("t1","t2","t3","t4"),3), value=c(0,1,1,1,0,0.5,1,1,0,0,1,1))

> dft
   line time value
1    X1   t1   0.0
2    X1   t2   1.0
3    X1   t3   1.0
4    X1   t4   1.0
5    X2   t1   0.0
6    X2   t2   0.5
7    X2   t3   1.0
8    X2   t4   1.0
9    X3   t1   0.0
10   X3   t2   0.0
11   X3   t3   1.0
12   X3   t4   1.0

I would like to plot it so, that whenever lines overlap, they are thicker relative to how many lines there are. So that for the moment when value starts at 1 and ends at 1, the line would be thicker if more lines have the same transition at the same point in time.

The same data could also be represented as transition frequencies

transitions <- data.frame(line=character(), generation=character(), t0=numeric(),t1=numeric())
for (line in unique(dft$line)){
  for (number in 1:3)  {
    generation= c("t1","t2","t3","t4")[number]
    generation2= c("t1","t2","t3","t4")[number+1]
    transitions <- rbind(transitions, data.frame(line=line, generation=generation, t0=dft[dft$line == line & dft$time == generation ,]$value, t1=dft[dft$line == line & dft$time == generation2 ,]$value))

  }
}

> transitions
  line generation  t0  t1
1   X1         t1 0.0 1.0
2   X1         t2 1.0 1.0
3   X1         t3 1.0 1.0
4   X2         t1 0.0 0.5
5   X2         t2 0.5 1.0
6   X2         t3 1.0 1.0
7   X3         t1 0.0 0.0
8   X3         t2 0.0 1.0
9   X3         t3 1.0 1.0

This sounds like a common problem. I did find some answers to how thickness could be varied, but not really on the basis of frequency. Can anyone point me in the right direction? Thanks!

Updated: Eventually each line (X1,X2,X3) should be traced as they go through time t1:t4, with time on the x axis and value on the y axis. Like the picture below (generated with the preliminary solution below). Perhaps there are tools in R that would make for nicer graphics though.

Example result

like image 574
puslet88 Avatar asked Oct 28 '25 07:10

puslet88


2 Answers

I also stumbled over the problem. I solved it with using the frequency as width of the line segment with ggplot.

dft <- data.frame(
  line = c(rep("X1", 4), rep("X2", 4), rep("X3", 4)), 
  time = rep(c("t1","t2","t3","t4"), 3), 
  value = c(0,1,1,1,0,0.5,1,1,0,0,1,1))

# you need a data frame with each transition and the frequency for it
dft_wide <- dft %>% pivot_wider( names_from = "time", values_from = "value")
# which columns are the different time transitions
t <- 2:5
t_seq <- paste(t, t+1, sep = ":")[-length(t)]
timeseq <- 1:4

# add the frequency for each transition
freqtable <- data.frame()
for (i in 1:length(t_seq)){
  temp <- eval(parse(text = paste0("dft_wide[", t_seq[[i]],"]"))) %>% group_by_all %>% count()
  names(temp) <- c("from", "to", "n")
  freqtable <- rbind.data.frame(freqtable, 
                                cbind.data.frame(temp, 
                                                 trans = t_seq[[i]],
                                                 tstart = timeseq[[i]], 
                                                 tend = timeseq[[i+1]]))
}

#draw the transition as separate segments and use the frequency as line width 
freqtable %>%
  ggplot(aes ( x = tstart, xend = tend, y = from, yend = to ))+
  geom_segment(aes(lwd = n))

Output 1 If you only have two timepoints it's easier:

dft_2 <- data.frame(t1 = c(0,1,0,0,2, 1, 1), t2 = c(1,1,1,2,1,1,1))

data.frame(table(dft_2$t1, dft_2$t2)) %>%
  mutate(transition = paste(Var1, Var2))%>%
  pivot_longer(cols = c(Var1, Var2), names_to = "x", values_to = "y")%>%
  filter(Freq != 0 & !grepl("NA", transition )) %>%
  ggplot(aes ( x = x, y = y, group = transition ))+
    geom_point()+
    geom_line(aes(lwd = Freq, ))

output 2

It's a personal judgment if this is considered "a nicer plot".

like image 178
PStaus Avatar answered Oct 31 '25 08:10

PStaus


Here's a quickplot by changing the transparency of the line.

enter image description here

dft$x <- dft$time
levels(dft$x) <- 0:3
dft$x <- as.numeric(dft$x)
ggplot(dft, aes(x, value, group=line)) + geom_line(size=1, alpha=0.15)
like image 22
Adam Quek Avatar answered Oct 31 '25 07:10

Adam Quek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!