grouping multiple gradients using ggplot2

2019-07-07 09:43发布

I'm quite new to R, so I apologize if the answer should be obvious, or if my data is organized poorly.

I am trying to graph the difference in sound characters (entropy) over time. I have used time signature information to break the recordings up into "bouts." I am able to create a scatterplot in which lines correspond to the bout number (0-9).

The code looks like so:

newbout <- a$start_on
signal <- diff(newbout)

Faulkner <- data.frame(Time=a$start_on[1:length(signal)],Entropy=a$min_ent[1:length(signal)])
Gatsby <- data.frame(x=Faulkner$Entropy[2:length(Faulkner$Entropy)],
    y=Faulkner$Entropy[1:length(Faulkner$Entropy)-1],
    z=Faulkner$Time[1:length(Faulkner$Time)-1])
Gatsby$grp <- cumsum(signal[1:length(signal)-1]<0)

require(ggplot2)
require(grid)
b <- ggplot(Gatsby, aes(x = x, y = y)) + 
    geom_point(size = 2,aes(color=grp)) + 
    geom_path(aes(color=grp)) +
    xlab("Min entropy") + ylab("Min entropy") + ggtitle("a408 d136") + 
    theme(axis.text=element_text(size=10),
      axis.title=element_text(size=10), plot.title=element_text(size=10))
b

The data frame itself looks like this:

        x     y           z grp
1   -3.90 -2.06   111.74600   0
2   -3.67 -3.90   224.49000   0
3   -3.08 -3.67   454.96600   0
4   -4.14 -3.08   643.53700   0
5   -2.37 -4.14   735.32900   0
6   -2.79 -2.37   821.13400   0
7   -6.96 -2.79   883.99100   0
8   -6.05 -6.96   946.84800   0
9   -3.19 -6.05  1045.62000   0
10  -2.74 -3.19  1244.17000   0
11  -3.23 -2.74  1511.56000   0
12  -3.57 -3.23  1632.29000   0
13  -2.74 -3.57  1729.07000   0
14  -3.99 -2.74  1814.88000   0
15  -6.70 -3.99  1875.74000   0
16  -6.63 -6.70  1936.60000   0
17  -4.06 -6.63  2037.37000   0
18  -3.29 -4.06  2247.89000   1
19  -4.91 -3.29     1.99546   1
20  -4.19 -4.91   230.47600   1
21  -2.31 -4.19   458.95700   1
22  -2.03 -2.31   995.73700   1
23  -3.43 -2.03  1122.45000   1
24  -3.75 -3.43  1240.18000   1
25  -2.56 -3.75  1334.97000   1
26  -4.19 -2.56  1417.78000   1

It is currently really difficult to visualize the beginning and the end of individual bouts on the plot. Is it possible to assign a different gradient for each group, without having to create a separate dataframe for each bout and adding paths manually? Ideally, I'd like to have something like, bout 0 is blue (and goes from light to dark), bout 1 is green (and goes from light to dark), where the gradient scale is controlled by the time variable, z. Any suggestions would be greatly appreciated!

标签: r ggplot2
2条回答
对你真心纯属浪费
2楼-- · 2019-07-07 10:17

If your goal is to make the start and end points of each path more prominent, you might do that by simply changing the point shape for these points only, demonstrated here:

require(ggplot2)
require(grid)
start <- aggregate(cbind(x,y)~grp,Gatsby,head,1)
end   <- aggregate(cbind(x,y)~grp,Gatsby,tail,1)
b <- ggplot(Gatsby, aes(x = x, y = y, color=factor(grp))) + 
  geom_point(data=start, size=4, shape=3, color="black") +
  geom_point(data=end,   size=5, shape=18) +
  geom_point(size = 2) + 
  geom_path(size=1) +
  scale_color_manual(values=c("blue","green")) +
  xlab("Min entropy") + ylab("Min entropy") + ggtitle("a408 d136") + 
  theme(axis.text=element_text(size=10),
        axis.title=element_text(size=10), plot.title=element_text(size=10))
b

This overlays a + on the starting point, and a diamond on the end-point, but you can tweak that as you like.

To make the colors go from light to dark, based on z, you could use the alpha aesthetic, as suggested in the comment:

b <- ggplot(Gatsby, aes(x = x, y = y, color=factor(grp))) + 
  geom_point(size = 2) + 
  geom_path(aes(alpha=z/max(z)),size=1) +
  scale_color_manual(values=c("blue","green")) +
  scale_alpha_continuous(guide="none")+
  xlab("Min entropy") + ylab("Min entropy") + ggtitle("a408 d136") + 
  theme(axis.text=element_text(size=10),
        axis.title=element_text(size=10), plot.title=element_text(size=10))
b

You could also combine the two approaches, but frankly that seems more confusing.

Finally, for diagnostic purposes, you might find a rotatable 3D plot (with z as the time axis), more informative.

library(rgl)
colors <- ifelse(Gatsby$grp==0,"blue","red")
max.z  <- aggregate(z~grp,Gatsby,max)
Gatsby$zNew <- with(Gatsby,ifelse(grp==0,z,z+max.z[max.z$grp==0,]$z))
with(Gatsby,open3d(scale=c(x=1/diff(range(x)),y=1/diff(range(y)),z=1/diff(range(z)))))
with(Gatsby,lines3d(x,y,zNew,  col=colors))
with(Gatsby,points3d(x,y,zNew, col=colors))
axes3d()
title3d(x="X",y="Y",z="Time")

[Note: In all of the above, I moved row 18 from grp 1 to grp 0.]

查看更多
太酷不给撩
3楼-- · 2019-07-07 10:31

Multiple color gradients may not be the best way to visualize the data, and ggplot doesn't really support that, but something like what you describe could be achieved with a combination of color and alpha gradients:

d <- data.frame(x=rep(1:20, 5), y=rnorm(100, 5, .2) + rep(1:5, each=20), z=rep(1:20, 5), grp=factor(rep(1:5, each=20)))

ggplot(d) +
  geom_path(aes(x, y, color=grp), size=2) +
  geom_path(aes(x, y, group=grp, alpha=z), size=2)

enter image description here

查看更多
登录 后发表回答