修复 plotly 色标中断
fix plotly color scale breaks
我使用 plotly 的 R 界面创建了一个热图,如下所示:
df <- data.frame(date = rep(seq(ymd('2016-09-01'), ymd('2016-09-10'), by='day'), each=2),
period = rep(c('lunch', 'dinner'), times=10),
diff=rnorm(20))
df %>%
plot_ly(x = date,
y = period,
z = abs(diff),
type = "heatmap",
hoverinfo='none',
colors = rev(RColorBrewer::brewer.pal(5, "RdYlGn")),
showscale = F) %>%
add_trace(x = date,
y = period,
text = paste0(round(diff*100), '%'),
mode='text',
hoverinfo='none')
产生这个:
有什么办法可以修复色标断裂的问题吗?我希望色标的中点为 20%,任何超过 50% 的值都在色标末端用红色着色。
好吧,热图通常应该具有随元素值而变化的颜色,但您可以根据您想要的任何标准将每个元素强制分为 5 组中的 1 组,并相应地分配 5 种颜色。然后,该分组将传递到 z。 z 应该是一个数字,而不是一个因子,因此您可以将分组转换为整数:
# create 5 levels or groups for the diff variable
# choose breaks as desired
diffLevel <- cut(abs(df$diff),
breaks = c(0, 0.0625, .125, .3, .5, Inf))
df %>%
plot_ly(x = date,
y = period,
z = as.integer(diffLevel),
type = "heatmap",
hoverinfo='none',
colors = rev(RColorBrewer::brewer.pal(5, "RdYlGn")),
showscale = F) %>%
add_trace(x = date,
y = period,
text = paste0(round(diff*100), '%'),
mode='text',
hoverinfo='none')
另一种方法是将 zmax
值设置为 0.5(和 zauto = FALSE
)。这不一定会将色标的中心设置为 .2,但它工作得很好,并建立了 0.5 的截止值,高于该值的一切都是红色的。它还允许你直接传入abs(diff)
:
df %>%
plot_ly(x = date,
y = period,
z = abs(diff),
zauto = FALSE, # set this to FALSE!
zmax = 0.5,
type = "heatmap",
hoverinfo='none',
colors = rev(RColorBrewer::brewer.pal(5, "RdYlGn")),
showscale = F) %>%
add_trace(x = date,
y = period,
text = paste0(round(diff*100), '%'),
mode='text',
hoverinfo='none')
最后一种方法是使用自定义色阶。我发现这很难以正确的格式获取 colorscale 参数。可能有更好的方法来做到这一点,但我无法想出任何优雅的方法。
customPalette <- colorRampPalette(c("red", "yellow", "green"))(61)
# I put 30 values between 0 and .2 and and 30 between .2 and 1.
# And so, my palette has 61 colors
customColors <- setNames(
data.frame(breaks = c(seq(0, .2, length.out = 31), seq(.21, 1, length.out = 30)),
colors = as.character(
apply(col2rgb(rev(customPalette)), 2, function(ii)
paste("rgb(", paste(ii, collapse = ","),")", sep = ""))),
stringsAsFactors = FALSE),
NULL)
# not perfect, but it seems to work decently
# initialize a list
colList <- list()
colList[[dim(customColors)[1]]] <- 0
# format custom color list
for(i in seq_len(dim(customColors)[1])) {
colList[[i]] <- c(customColors[i, 1], customColors[i, 2])
}
# set zmax = 0.5 and zauto = FALSE
df %>%
plot_ly(x = date,
y = period,
z = abs(diff),
zauto = FALSE,
zmax = 0.5,
type = "heatmap",
hoverinfo='none',
colorscale = colList,
showscale = F) %>%
add_trace(x = date,
y = period,
text = paste0(round(diff*100), '%'),
mode='text',
hoverinfo='none')
我使用 plotly 的 R 界面创建了一个热图,如下所示:
df <- data.frame(date = rep(seq(ymd('2016-09-01'), ymd('2016-09-10'), by='day'), each=2),
period = rep(c('lunch', 'dinner'), times=10),
diff=rnorm(20))
df %>%
plot_ly(x = date,
y = period,
z = abs(diff),
type = "heatmap",
hoverinfo='none',
colors = rev(RColorBrewer::brewer.pal(5, "RdYlGn")),
showscale = F) %>%
add_trace(x = date,
y = period,
text = paste0(round(diff*100), '%'),
mode='text',
hoverinfo='none')
产生这个:
有什么办法可以修复色标断裂的问题吗?我希望色标的中点为 20%,任何超过 50% 的值都在色标末端用红色着色。
好吧,热图通常应该具有随元素值而变化的颜色,但您可以根据您想要的任何标准将每个元素强制分为 5 组中的 1 组,并相应地分配 5 种颜色。然后,该分组将传递到 z。 z 应该是一个数字,而不是一个因子,因此您可以将分组转换为整数:
# create 5 levels or groups for the diff variable
# choose breaks as desired
diffLevel <- cut(abs(df$diff),
breaks = c(0, 0.0625, .125, .3, .5, Inf))
df %>%
plot_ly(x = date,
y = period,
z = as.integer(diffLevel),
type = "heatmap",
hoverinfo='none',
colors = rev(RColorBrewer::brewer.pal(5, "RdYlGn")),
showscale = F) %>%
add_trace(x = date,
y = period,
text = paste0(round(diff*100), '%'),
mode='text',
hoverinfo='none')
另一种方法是将 zmax
值设置为 0.5(和 zauto = FALSE
)。这不一定会将色标的中心设置为 .2,但它工作得很好,并建立了 0.5 的截止值,高于该值的一切都是红色的。它还允许你直接传入abs(diff)
:
df %>%
plot_ly(x = date,
y = period,
z = abs(diff),
zauto = FALSE, # set this to FALSE!
zmax = 0.5,
type = "heatmap",
hoverinfo='none',
colors = rev(RColorBrewer::brewer.pal(5, "RdYlGn")),
showscale = F) %>%
add_trace(x = date,
y = period,
text = paste0(round(diff*100), '%'),
mode='text',
hoverinfo='none')
最后一种方法是使用自定义色阶。我发现这很难以正确的格式获取 colorscale 参数。可能有更好的方法来做到这一点,但我无法想出任何优雅的方法。
customPalette <- colorRampPalette(c("red", "yellow", "green"))(61)
# I put 30 values between 0 and .2 and and 30 between .2 and 1.
# And so, my palette has 61 colors
customColors <- setNames(
data.frame(breaks = c(seq(0, .2, length.out = 31), seq(.21, 1, length.out = 30)),
colors = as.character(
apply(col2rgb(rev(customPalette)), 2, function(ii)
paste("rgb(", paste(ii, collapse = ","),")", sep = ""))),
stringsAsFactors = FALSE),
NULL)
# not perfect, but it seems to work decently
# initialize a list
colList <- list()
colList[[dim(customColors)[1]]] <- 0
# format custom color list
for(i in seq_len(dim(customColors)[1])) {
colList[[i]] <- c(customColors[i, 1], customColors[i, 2])
}
# set zmax = 0.5 and zauto = FALSE
df %>%
plot_ly(x = date,
y = period,
z = abs(diff),
zauto = FALSE,
zmax = 0.5,
type = "heatmap",
hoverinfo='none',
colorscale = colList,
showscale = F) %>%
add_trace(x = date,
y = period,
text = paste0(round(diff*100), '%'),
mode='text',
hoverinfo='none')