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.
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))
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, ))
It's a personal judgment if this is considered "a nicer plot".