R 是否可以在绘图上进行多个剪辑?
我编辑这篇文章是为了提供一个更好的例子来说明我需要什么。我会保留在底部的原始信息,以防有帮助 我有以下数据:R 是否可以在绘图上进行多个剪辑?,r,clip,R,Clip,我编辑这篇文章是为了提供一个更好的例子来说明我需要什么。我会保留在底部的原始信息,以防有帮助 我有以下数据: x=c(1,2,7,3,4,8,9,5,6,7,11,13,15,8,9,10,11,12,13,15) y=c(2:10,9,8,7,6,8,10,11,12,13,14,1) date=strptime(20010101:20010120,'%Y%m%d') z=data.frame(date,x,y) z$diff=z$y-z$x z$min=pmin(x,y) z$max=pma
x=c(1,2,7,3,4,8,9,5,6,7,11,13,15,8,9,10,11,12,13,15)
y=c(2:10,9,8,7,6,8,10,11,12,13,14,1)
date=strptime(20010101:20010120,'%Y%m%d')
z=data.frame(date,x,y)
z$diff=z$y-z$x
z$min=pmin(x,y)
z$max=pmax(x,y)
所以我的数据是:
date x y diff min max
1 2001-01-01 1 2 1 1 2
2 2001-01-02 2 3 1 2 3
3 2001-01-03 7 4 -3 4 7
4 2001-01-04 3 5 2 3 5
5 2001-01-05 4 6 2 4 6
6 2001-01-06 8 7 -1 7 8
7 2001-01-07 9 8 -1 8 9
8 2001-01-08 5 9 4 5 9
9 2001-01-09 6 10 4 6 10
10 2001-01-10 7 9 2 7 9
11 2001-01-11 11 8 -3 8 11
12 2001-01-12 13 7 -6 7 13
13 2001-01-13 15 6 -9 6 15
14 2001-01-14 8 8 0 8 8
15 2001-01-15 9 10 1 9 10
16 2001-01-16 10 11 1 10 11
17 2001-01-17 11 12 1 11 12
18 2001-01-18 12 13 1 12 13
19 2001-01-19 13 14 1 13 14
20 2001-01-20 15 1 -14 1 15
我想创建一个多边形图,其中多边形的颜色根据z$diff小于零时的变化而变化。所以图应该是这样的:
我知道线段可以处理直线,但不幸的是,我需要处理多边形
原始信息:
假设我有以下数据:
x=rnorm(100)
y=rnorm(100)
date=strptime(20010101:20010410,'%Y%m%d')
date=date[complete.cases(date)]
z=data.frame(date,x,y)
z$max=apply(z[2:3],1,which.max)
z$min=apply(z[2:3],1,which.min)
z$v=z$max-z$min
w=z[z$v<0,]
当数据帧w
中存在间隙时,多边形会覆盖这些间隙。我知道如何使用clip来剪裁一个区域,但它可以用来剪裁数据帧中的多个间隙吗
理想情况下,每当y>x时,
w
多边形应在z
多边形上重叠。我建议您使用z和w的不同列名称合并单个数据帧上的所有数据
names(w) <- c('date1','x1','y1','max1','min1','v1')
kk <- merge(z,w, by.x='date', by.y='date1', all.x=TRUE)
plot(kk$date,kk$x,type='n')
polygon(c(kk$date,kk$date[nrow(kk):1]),c(kk$x,kk$y[nrow(kk):1])
,col='skyblue',border=NA)
polygon(c(kk$date,kk$date[nrow(kk):1]), c(kk$x1,kk$y1[nrow(kk):1])
,col='salmon',border=NA)
names(w)在仅由NA
组成的数据中,可以通过一条线分隔多边形
library(reshape2)
library(ggplot2)
z <- data.frame(
date=date,
min=pmin(x, y),
max=pmax(x, y),
series=ifelse(x>y, 1, 2)
)
# Helper function to create closed polygon, optionally adding NA line at bottom
rdata <- function(dat, addNA=FALSE){
rdat <- dat[nrow(dat):1, ]
ret <- rbind(
data.frame(x= dat$date, y= dat$max, series= dat$series),
data.frame(x=rdat$date, y=rdat$min, series=rdat$series)
)
if(addNA) ret <- rbind(ret, c(NA, NA, NA))
ret
}
# Closed polygon 1
rz <- rdata(z)
#Closed polygon 2
z2 <- z
rlez <- rle(z$series)$lengths
z2$chunk <- rep(seq_along(rlez), times=rlez)
rz2 <- ddply(z2, .(chunk), rdata, addNA=TRUE)
rz2 <- rz2[rz2$series!=1, ]
另外,我不知道你的数据在现实生活中代表了什么,但我的直觉是,如果你使用geom_linerange
而不是多边形,你可以更好地(或者至少也可以)可视化它,而且花费的精力要少得多
ggplot(z, aes(x=date, ymin=min, ymax=max, colour=factor(series))) +
geom_linerange(size=5)
与@Andrie选择的方向不同。我发现使用geom_ribbon
更直观(我确信它在某种程度上只是geom_polygon
的包装器)
您没有很好地指定如何处理长度为1的块。从技术上讲,这样一个区块的“多边形”只是一个垂直线段。对我来说,更直观的是让这些块在两个方向上略微延伸,以“在中间相遇”
#构造类似的数据
x=c(1,2,7,3,4,8,9,5,6,7,11,13,15,8,9,10,11,12,13,15)
y=c(2:10,9,8,7,6,8,10,11,12,13,14,1)
日期=strtime(20010101:20010120,“%Y%m%d”)
z=数据帧(日期,x,y)
z$diff=z$y-z$x
z$min=pmin(x,y)
z$max=pmax(x,y)
#为每个区块分配一个唯一的整数
tmp(0)
z$series我今天在玩这个,看看是否有可能使用一种优雅的基本方法。下面是一个简单的基本方法:
x=c(1,2,7,3,4,8,9,5,6,7,11,13,15,8,9,10,11,12,13,15)
y=c(2:10,9,8,7,6,8,10,11,12,13,14,1)
date=strptime(20010101:20010120,'%Y%m%d')
z=data.frame(date,x,y)
z$diff=z$y-z$x
z$min=pmin(x,y)
z$max=pmax(x,y)
zp=z[z$diff>0,]
zn=z[z$diff<0,]
plot(z$date,z$max,type='n',ylim=range(0,max(z$max)))
segments(zp$date,zp$min,zp$date,zp$max,col='skyblue',lwd=10,lend=1)
segments(zn$date,zn$min,zn$date,zn$max,col='salmon',lwd=10,lend=1)
x=c(1,2,7,3,4,8,9,5,6,7,11,13,15,8,9,10,11,12,13,15)
y=c(2:10,9,8,7,6,8,10,11,12,13,14,1)
日期=strtime(20010101:20010120,“%Y%m%d”)
z=数据帧(日期,x,y)
z$diff=z$y-z$x
z$min=pmin(x,y)
z$max=pmax(x,y)
zp=z[z$diff>0,]
zn=z[z$diffYes,是的。每次你的多边形遇到一个带有NA值的行时,它都会被剪裁。我用你的数据尝试了它,它在原则上是有效的,但我无法理解你的数据操作,所以没有给出答案。我不确定这是否正确。如果我理解查询者想要什么,它最终会变成一个多边形,每个c对应一个z中的相邻范围,其中z$vAh棘手的一点是,您必须反转每个段中y值的顺序-反转整个向量将不起作用。Spacedman,我将边框从NA更改为各自的颜色,以处理只有一行的多边形。是的,w
数据帧需要某种方式反转分段。我想如果所有其他方法都失败了,我将求助于找出一种方法,用每一个连续的行序列生成多个数据帧,然后用它生成多个多边形。不过,我的数据可以追溯到1960年,我真的很想避免这种情况。安德烈,对不起,我对R很陌生,我的数据处理还有很多需要改进的地方基本上,我为这个例子创建了两组随机数,创建了一个日期字段,然后出于某种原因消除了我在两个月之间得到的NA。然后,我将所有这些都放在一个数据框中,并计算出y是否大于x。我的实际数据中有两列以上,这就是为什么我选择了max和min。如果x大于x,我希望不要让这些多边形的颜色与y更大的多边形的颜色不同。希望这能让它更清晰一点。我可能不应该在这个例子中使用随机数。不幸的是,这不是我想要的。我没有尝试合并,但我尝试在vThanks时用NAs替换所有x和y。线条范围是一个更好的选择。我还计算了o但在base中使用一种不太优雅的方式:绘图(b$Date,b$Max,type='h',col='skyblue');线条(w$Date,w$Max,type='h',col='salmon');线条(b$Date,b$Min,type='h',col='white'))
。不是很优雅,但现在我将开始学习ggplot,因为它的功能给我留下了深刻的印象。是的,我很担心安德烈的第一个解决方案是如何处理色带持续了多少天。我太执着于多边形了,我没有考虑使用条形图。我如何才能对两个答案给予奖励?你的两个答案都让我陷入了困境我不想一个人去。
ggplot(z, aes(x=date, ymin=min, ymax=max, colour=factor(series))) +
geom_linerange(size=5)
#Construct similar data
x=c(1,2,7,3,4,8,9,5,6,7,11,13,15,8,9,10,11,12,13,15)
y=c(2:10,9,8,7,6,8,10,11,12,13,14,1)
date=strptime(20010101:20010120,'%Y%m%d')
z=data.frame(date,x,y)
z$diff=z$y-z$x
z$min=pmin(x,y)
z$max=pmax(x,y)
#Assign a unique integer to each chunk
tmp <- rle(z$diff > 0)
z$series <- rep(1:length(tmp$lengths),times = tmp$lengths)
#Grab just the useful columns
z1 <- z[,c(1,4:7)]
#This is the ugly part.
# Loop through data and add a row
# at the transitions
for (i in 2:nrow(z1)){
if (z1$series[i] != z1$series[i-1]){
newRow <- colwise(mean)(z1[c(i,i-1),])
newRow1 <- newRow2 <- newRow
newRow1$series <- z1$series[i-1]; newRow2$series <- z1$series[i]
newRow1$diff <- z1$diff[i-1]; newRow2$diff <- z1$diff[i]
z1 <- rbind(z1,newRow1,newRow2)
}
}
#Put everything back in order
z1 <- arrange(z1,date)
#Create a factor to build the legend with
z1$diff <- sign(z1$diff)
z1$grp <- factor(ifelse(z1$diff > 0,"Greater Than","Less Than"))
#The only clever bit ;)
ribbons <- dlply(z1,.(series),.fun = function(x){geom_ribbon(data = x,aes(ymin = min,ymax = max,fill = grp))})
p <- ggplot(z1,aes(x = date, ymin = min,ymax = max,fill = grp)) +
ribbons +
labs(x = NULL,y = NULL,fill = "Legend")
x=c(1,2,7,3,4,8,9,5,6,7,11,13,15,8,9,10,11,12,13,15)
y=c(2:10,9,8,7,6,8,10,11,12,13,14,1)
date=strptime(20010101:20010120,'%Y%m%d')
z=data.frame(date,x,y)
z$diff=z$y-z$x
z$min=pmin(x,y)
z$max=pmax(x,y)
zp=z[z$diff>0,]
zn=z[z$diff<0,]
plot(z$date,z$max,type='n',ylim=range(0,max(z$max)))
segments(zp$date,zp$min,zp$date,zp$max,col='skyblue',lwd=10,lend=1)
segments(zn$date,zn$min,zn$date,zn$max,col='salmon',lwd=10,lend=1)