5

For lack of a better name, I want to create a continous 1-d heatmap in R, i.e. a 1-d version of this question

Toy data to use:

df <- data.frame(x=1:20,
  freq=c(8, 7, 5, 6, 10, 4, 2, 9, 3, 10, 1, 8, 4, 7, 2, 6, 7, 6, 9, 9))

I can create a crude gridded output using

ggplot(data=df, aes(x=x, y=1)) + geom_tile(aes(fill=freq))

but similar to the other question, I'd like to have a smooth colour transition instead. Unfortunately, I don't understand the 2-d answer well enough to adapt it to 1-d.

Community
  • 1
  • 1
Ricky
  • 4,616
  • 6
  • 42
  • 72

2 Answers2

4

Since your data are frequencies, it makes more sense to me to present them as raw data:

df2 <- unlist(apply(df, 1, function(x) rep(x[1], x[2])))

Then I would use the kernel density to create a smooth representation of your categories:

df2 <- density(df2, adjust = 1)
df2 <- data.frame(x = df2$x, y = df2$y) #shouldn't there be an as.data.frame method for this?

And then plot as tiles:

ggplot(df2, aes(x = x, y = 1, fill = y)) + geom_tile()

You can use the adjust argument in the density call to change the level of smoothing.

Adjust 1 (default): plot1 Adjust 0.5: plot2 Adjust 0.3: plot3

Axeman
  • 32,068
  • 8
  • 81
  • 94
  • Thanks, appearance-wise this is what I was looking for. However the smoothed levels don't look as much like my original gridded version: the smooth version seems to be much darker at the sides rather than centre, while my original has darker columns in the middle. I'd like to be able to reflect the same level of colour intensities – Ricky Aug 02 '15 at 03:46
1

I'm not totally sure I understood what you want, but this is an attempt to solve [what I think is] your problem:

First, the vector you have is very short, and the changes on freq are very abrupt, so that will make for a very "tile-like" feeling of the plot. You'll need to address that first. My approach is using a spline interpolation:

 newdf=data.frame(x=spline(df)[[1]],freq=spline(df)[[2]],y=rep(1,times=3*length(df$x)))

Please notice that I also created a y vector in the data frame.

Now it can be plotted using lattice's levelplot:

levelplot(freq~x*y,data=newdf)

Which produces a smoother plot (as I understand, that's what you need). It can be also plotted with ggplot:

ggplot(newdf,aes(x=x,y=y,fill=freq))+geom_tile()

========== EDIT TO ADD ============

Please notice that you can control the new vector length with spline's n argument, making for an even smoother transition (spline(df,n=100)[[1]]) If you follow this option, make sure you adjust the times you repeat 1 in y's definition!!. Default n is 3x the length of the input vector.

PavoDive
  • 6,322
  • 2
  • 29
  • 55
  • Thanks ,this seems to be displaying what I want. Just curious, it seems like I don't need the vector y, since the value is always 1, so I can just replace it with one in `levelplot` or `ggplot` . Am I missing something? – Ricky Aug 02 '15 at 03:47
  • Good it addressed your needs. Regarding Y, you can define as 1 directly in the plotting call, as you say. If this answered your question, you might consider checking it as accepted. – PavoDive Aug 02 '15 at 09:11