使用由组和比例确定的填充渐变绘制矩形
Plotting Rectangles with Fill Gradients Determined by Group and Proportions
我正在尝试绘制一堆矩形,其中填充是按比例确定的颜色渐变。
首先,我有一个像这样的数据框:
sampleID 1 2 3 4 5 ... 100
sample1 1 1 1 1 1 ... 1
sample2 1 1 1 1 1 ... 1
sample3 2 2 2 2 2 ... 2
sample4 2 2 1 1 2 ... 2
...
其中整数对应于我进行的 100 次分析的组分配。我希望具有混合组分配的样本具有颜色渐变(例如,样本 4 是 25% 的蓝色和 75% 的红色)。
这是我的代码:
library("RColorBrewer")
library("plotrix")
# Make sampleID column rownames and remove from df
col2rownames <- function(df){
rownames(df) <- df$sampleID
df$sampleID <- NULL
return(df)
}
df <- col2rownames(df)
# Get a list of frequency tables corresponding to each row in df.
df.freq <- apply(df, 1, table)
# Convert list of table() objects to list of data.frames
df.freq <- lapply(df.freq, function(x) { as.data.frame(x, stringsAsFactors = F) } )
# Make color vector
colors <- c(
"1" = "#808080", # BXCH
"2" = "purple4", # BXON
"3" = "yellow3", # BXFL
"4" = "orange1", # BXEA
"5" = "mediumaquamarine", # BXFL second cluster
"6" = "magenta3", # GUFL
"7" = "blue", # GUMS
"8" = "red", # BXMX
"9" = "green2", # BXTT
"10" = "#00ffff" # BXDS
)
# Subset only colors present in each df.freq data.frame
collist <- list()
collist <- lapply(df.freq, function(x) {
colors[x[, 1]]
})
# Convert to list of vectors
collist <- lapply(collist, as.vector)
# Get number of data frames in list
mylen <- length(df.freq)
# Plot an empty box
plot(1:mylen, type="n", axes=F)
# Initialize counters
counter_min <- 0
counter_max <- 1
# Initialize newcollist
newcollist <- list()
# Plot rectangles with color gradient
for (i in 1:length(collist)){
colsubset <- c(collist[[i]])
newcollist[[i]] <- colsubset
gradient.rect(xleft = 0, ybottom = counter_min, xright = 5, ytop = counter_max, col = colsubset, gradient = "x")
counter_min <- counter_max
counter_max <- counter_min + 1
}
这是我当前的输出:
Rectangle Gradient Plot
但是,>1 种颜色的矩形显示为 50/50,这不是正确的比例。例如,顶部附近的紫色和浅蓝色实际上应该分别为 88% 和 12%。
我被困在这里了。有谁知道按比例绘制颜色填充的方法吗?
非常感谢您的宝贵时间。
好的,所以这更多是 gradient.rect()
函数的问题。它根本不是为您想要的而制作的。无论如何,它总是会产生均等分割的矩形。
然而,这并不意味着你不能制作你的情节。您只需要使用 good'ol rect()
函数并自己计算拆分即可。
我从你的 post...
中得到了我能做的虚拟数据
df <- "sampleID,1,2,3,4,5
sample1,1,1,1,1,1
sample2,1,1,1,1,1
sample3,2,2,2,2,2
sample4,2,2,1,1,2
sample5,3,2,1,1,2
sample6,4,4,4,1,2
sample7,2,2,1,2,2"
df <- read.table(text = df, h = T, sep = ",", row.names = 1)
这一切都没有改变:
col2rownames <- function(df){
rownames(df) <- df$sampleID
df$sampleID <- NULL
return(df)
}
df <- col2rownames(df)
df.freq <- apply(df, 1, table)
df.freq <- lapply(df.freq, function(x) { as.data.frame(x, stringsAsFactors = F) } )
colors <- c(
"1" = "#808080", # BXCH
"2" = "purple4", # BXON
"3" = "yellow3", # BXFL
"4" = "orange1", # BXEA
"5" = "mediumaquamarine", # BXFL second cluster
"6" = "magenta3", # GUFL
"7" = "blue", # GUMS
"8" = "red", # BXMX
"9" = "green2", # BXTT
"10" = "#00ffff" # BXDS
)
collist <- list()
collist <- lapply(df.freq, function(x) {
colors[x[, 1]]
})
collist <- lapply(collist, as.vector)
mylen <- length(df.freq)
这是新内容:
# Plot an empty box
plot(c(0,1), c(0, mylen), type="n", axes=F)
# Initialize counter (you don't really need 2 for this...)
counter <- 0
# Plot rectangles of given colors, split by given freqs
rect_split <- function(freqs, colors, ybot, ytop, xleft = 0, xright = 1, ...){
freqs <- freqs/sum(freqs) # norm to 1
xpos <- c(0, cumsum(freqs)) # get splits for colors
xpos <- (xpos - xleft)/(xright - xleft) # scale between xleft and xright
sapply(seq_along(freqs), function(i){
rect(xleft = xpos[i], xright = xpos[i+1], ybottom = ybot, ytop = ytop, col = colors[i], ...)
})
}
for (i in 1:length(collist)){
cols <- c(collist[[i]])
freqs <- df.freq[[i]][, 2] # assuming the freqs are in the order of the colors
rect_split(freqs, cols, ybot = counter, ytop = counter + 1)
counter <- counter + 1
}
这个情节:
我正在尝试绘制一堆矩形,其中填充是按比例确定的颜色渐变。
首先,我有一个像这样的数据框:
sampleID 1 2 3 4 5 ... 100
sample1 1 1 1 1 1 ... 1
sample2 1 1 1 1 1 ... 1
sample3 2 2 2 2 2 ... 2
sample4 2 2 1 1 2 ... 2
...
其中整数对应于我进行的 100 次分析的组分配。我希望具有混合组分配的样本具有颜色渐变(例如,样本 4 是 25% 的蓝色和 75% 的红色)。
这是我的代码:
library("RColorBrewer")
library("plotrix")
# Make sampleID column rownames and remove from df
col2rownames <- function(df){
rownames(df) <- df$sampleID
df$sampleID <- NULL
return(df)
}
df <- col2rownames(df)
# Get a list of frequency tables corresponding to each row in df.
df.freq <- apply(df, 1, table)
# Convert list of table() objects to list of data.frames
df.freq <- lapply(df.freq, function(x) { as.data.frame(x, stringsAsFactors = F) } )
# Make color vector
colors <- c(
"1" = "#808080", # BXCH
"2" = "purple4", # BXON
"3" = "yellow3", # BXFL
"4" = "orange1", # BXEA
"5" = "mediumaquamarine", # BXFL second cluster
"6" = "magenta3", # GUFL
"7" = "blue", # GUMS
"8" = "red", # BXMX
"9" = "green2", # BXTT
"10" = "#00ffff" # BXDS
)
# Subset only colors present in each df.freq data.frame
collist <- list()
collist <- lapply(df.freq, function(x) {
colors[x[, 1]]
})
# Convert to list of vectors
collist <- lapply(collist, as.vector)
# Get number of data frames in list
mylen <- length(df.freq)
# Plot an empty box
plot(1:mylen, type="n", axes=F)
# Initialize counters
counter_min <- 0
counter_max <- 1
# Initialize newcollist
newcollist <- list()
# Plot rectangles with color gradient
for (i in 1:length(collist)){
colsubset <- c(collist[[i]])
newcollist[[i]] <- colsubset
gradient.rect(xleft = 0, ybottom = counter_min, xright = 5, ytop = counter_max, col = colsubset, gradient = "x")
counter_min <- counter_max
counter_max <- counter_min + 1
}
这是我当前的输出:
Rectangle Gradient Plot
但是,>1 种颜色的矩形显示为 50/50,这不是正确的比例。例如,顶部附近的紫色和浅蓝色实际上应该分别为 88% 和 12%。
我被困在这里了。有谁知道按比例绘制颜色填充的方法吗?
非常感谢您的宝贵时间。
好的,所以这更多是 gradient.rect()
函数的问题。它根本不是为您想要的而制作的。无论如何,它总是会产生均等分割的矩形。
然而,这并不意味着你不能制作你的情节。您只需要使用 good'ol rect()
函数并自己计算拆分即可。
我从你的 post...
中得到了我能做的虚拟数据df <- "sampleID,1,2,3,4,5
sample1,1,1,1,1,1
sample2,1,1,1,1,1
sample3,2,2,2,2,2
sample4,2,2,1,1,2
sample5,3,2,1,1,2
sample6,4,4,4,1,2
sample7,2,2,1,2,2"
df <- read.table(text = df, h = T, sep = ",", row.names = 1)
这一切都没有改变:
col2rownames <- function(df){
rownames(df) <- df$sampleID
df$sampleID <- NULL
return(df)
}
df <- col2rownames(df)
df.freq <- apply(df, 1, table)
df.freq <- lapply(df.freq, function(x) { as.data.frame(x, stringsAsFactors = F) } )
colors <- c(
"1" = "#808080", # BXCH
"2" = "purple4", # BXON
"3" = "yellow3", # BXFL
"4" = "orange1", # BXEA
"5" = "mediumaquamarine", # BXFL second cluster
"6" = "magenta3", # GUFL
"7" = "blue", # GUMS
"8" = "red", # BXMX
"9" = "green2", # BXTT
"10" = "#00ffff" # BXDS
)
collist <- list()
collist <- lapply(df.freq, function(x) {
colors[x[, 1]]
})
collist <- lapply(collist, as.vector)
mylen <- length(df.freq)
这是新内容:
# Plot an empty box
plot(c(0,1), c(0, mylen), type="n", axes=F)
# Initialize counter (you don't really need 2 for this...)
counter <- 0
# Plot rectangles of given colors, split by given freqs
rect_split <- function(freqs, colors, ybot, ytop, xleft = 0, xright = 1, ...){
freqs <- freqs/sum(freqs) # norm to 1
xpos <- c(0, cumsum(freqs)) # get splits for colors
xpos <- (xpos - xleft)/(xright - xleft) # scale between xleft and xright
sapply(seq_along(freqs), function(i){
rect(xleft = xpos[i], xright = xpos[i+1], ybottom = ybot, ytop = ytop, col = colors[i], ...)
})
}
for (i in 1:length(collist)){
cols <- c(collist[[i]])
freqs <- df.freq[[i]][, 2] # assuming the freqs are in the order of the colors
rect_split(freqs, cols, ybot = counter, ytop = counter + 1)
counter <- counter + 1
}
这个情节: