Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
553 views
in Technique[技术] by (71.8m points)

ggplot2 - Place 1 heatmap on another with transparency in R

I'm new to R and have the following challenge;

I want to create a visualization that basically combines 2 kind of 'heatmaps' in order to visualize at what times there are truly dark skies (for astronomy). For this I want to have a heatmap that visualizes the brightness of the moon based on the moonrise and moonset times and the phase of the moon. On this then we can plot a 'band'like heatmap for the time the sun is up with some transparency. I'm not sure if this is going to work visualy or if I need to find some other solution, however this seems like a good challenge to get into R some more. But I could use some pointers as I'm stuck already loading the matrix of size 24(hours) x 31(days) with all the 720 values. When trying to create a basic data.frame from the vectors I get the error that the number of rows are inconsistent.

Furthermore I have some heatmap examples working already, but I'm not sure how to combine 2 of them in the same plot like I described.

As an illustration the current 'heatmap' as it is in excel

Current heatmap from excel

And some data:

MOON

moon <- structure(list(X1.9.12 = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L), .Label = c("0%", "100%"), class = "factor"), X2.9.12 = structure(c(2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L), .Label = c("0%", "98%"), class = "factor"), 
    X3.9.12 = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L
    ), .Label = c("0%", "94%"), class = "factor"), X4.9.12 = structure(c(2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L), .Label = c("0%", "89%"), class = "factor"), 
    X5.9.12 = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L
    ), .Label = c("0%", "82%"), class = "factor"), X6.9.12 = structure(c(2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L), .Label = c("0%", "74%"), class = "factor"), 
    X7.9.12 = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
    ), .Label = c("0%", "65%"), class = "factor"), X8.9.12 = structure(c(2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("0%", "56%"), class = "factor"), 
    X9.9.12 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L
    ), .Label = c("0%", "47%"), class = "factor"), X10.9.12 = structure(c(2L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("0%", "37%"), class = "factor"), 
    X11.9.12 = structure(c(2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L
    ), .Label = c("0%", "28%"), class = "factor"), X12.9.12 = structure(c(2L, 
    2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("0%", "20%"), class = "factor"), 
    X13.9.12 = structure(c(2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L
    ), .Label = c("0%", "12%"), class = "factor"), X14.9.12 = structure(c(2L, 
    2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L), .Label = c("0%", "6%"), class = "factor"), 
    X15.9.12 = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L
    ), .Label = c("0%", "2%"), class = "factor"), X16.9.12 = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "0%", class = "factor"), 
    X17.9.12 = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L
    ), .Label = c("0%", "1%"), class = "factor")), .Names = c("X1.9.12", 
"X2.9.12", "X3.9.12", "X4.9.12", "X5.9.12", "X6.9.12", "X7.9.12", 
"X8.9.12", "X9.9.12", "X10.9.12", "X11.9.12", "X12.9.12", "X13.9.12", 
"X14.9.12", "X15.9.12", "X16.9.12", "X17.9.12"), class = "data.frame", row.names = c("0:00:00", 
"1:00:00", "2:00:00", "3:00:00", "4:00:00", "5:00:00", "6:00:00", 
"7:00:00", "8:00:00", "9:00:00", "10:00:00", "11:00:00", "12:00:00", 
"13:00:00", "14:00:00", "15:00:00", "16:00:00", "17:00:00", "18:00:00", 
"19:00:00", "20:00:00", "21:00:00", "22:00:00", "23:00:00"))

SUN

    September   
Day Sunrise Sunset
1   6:52    20:26
2   6:54    20:24
3   6:56    20:22
4   6:57    20:20
5   6:59    20:17
6   7:00    20:15
7   7:02    20:13
8   7:04    20:10
9   7:05    20:08
10  7:07    20:06
11  7:08    20:05
12  7:09    20:02
13  7:11    20:00
14  7:13    19:58
15  7:14    19:55
16  7:16    19:53
17  7:17    19:51
18  7:19    19:48
19  7:21    19:46
20  7:22    19:44
21  7:25    19:40
22  7:26    19:38
23  7:28    19:35
24  7:30    19:33
25  7:31    19:31
26  7:33    19:28
27  7:35    19:26
28  7:36    19:24
29  7:38    19:21
30  7:40    19:19
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So from what I understood, there are basically two questions:

Data organization

The easiest would be, if you'd have all data in one data.frame in long format. I.e. for each combination of time and date you have one row, with additional columns for the moon and sun intensity.

So we start with melting and fixing the moon data:

library(reshape2)
moon$time <- row.names(moon)
moon <- melt(moon, id.vars="time", variable.name="date", value.name="moon" )
moon$date <- sub("X(.*)", "\1", moon$date)
moon$moon <- 1 - as.numeric(sub("%", "", moon$moon)) /100

Now we bring the sun data to an comparable form, by at least give them the same identifier for the date:

sun$Day <- paste( sun$Day, "9.12", sep  ="." )

Next step is to merge the data by the date resp. Day and to set a comparable column for the sun intensity as is given already for the moon intensity. This can be done by casting the times to a time format and compare Sunrise and Sunset with the actual time:

mdf <- merge( moon, sun, by.x = "date", by.y = "Day" )
mdf$time.tmp <- strptime(mdf$time, format="%H:%M")
mdf$Sunrise  <- round(strptime(mdf$Sunrise, format="%H:%M"), units = "hours")
mdf$Sunset   <- round(strptime(mdf$Sunset, format="%H:%M"), units = "hours")
mdf$sun <- ifelse( mdf$Sunrise <= mdf$time.tmp & mdf$Sunset >= mdf$time.tmp, 1, 0 )
mdf <- mdf[c("date", "time", "moon", "sun")]

mdf[ 5:10, ]
  date    time moon sun
1.9.12 4:00:00    0   0
1.9.12 5:00:00    0   0
1.9.12 6:00:00    0   0
1.9.12 7:00:00    0   1
1.9.12 8:00:00    1   1
1.9.12 9:00:00    1   1

Plotting

Adding multiple layers with different transparencies begs literally for ggplot2. In order to use this in a proper way, there is one more data manipulation necessary, which ensures the proper order on the axes: date and time have to be converted to factors with factor levels ordered not lexically, but by time:

mdf <- within( mdf, {
  date <- factor( date, levels=unique(date)[ order(as.Date( unique(date), "%d.%m.%y" ) ) ] )
  time <- factor( time,  levels=unique(time)[ order(strptime( time, format="%H:%M:%S"), decreasing=TRUE ) ] )
} )

This can be plot now:

library( ggplot2 )
ggplot( data = mdf, aes(x = date, y = time )  ) + 
  geom_tile( aes( alpha = sun  ), fill = "goldenrod1"  ) +
  geom_tile( aes( alpha = moon ), fill = "dodgerblue3" ) +
  scale_alpha_continuous( "moon", range=c(0,0.5) ) +
  theme_bw() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Which gives you the following result

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...