简体   繁体   English

自动调整自定义绘图字符的大小?

[英]Automatically resizing a custom plotting character?

Hey everybody I am hoping there is someone out there who can help me with plotting a custom made pch in R. In my case I am trying to create a graph relating to water quality over time. 嘿,我希望每个人都可以帮助我在R中绘制定制的pch。就我而言,我试图创建与水质有关的图形。 One way to monitor water quality is to use a secchi disc, which is basically a metal disc with quarters of the disc painted black and white (see the plot below). 监测水质的一种方法是使用secchi圆盘,该圆盘基本上是金属圆盘,四分之一圆盘涂有黑色和白色(请参见下图)。

So far I've been able to successfully create the disc and put it on a plot, but my problem comes with a stretching effect depending on the dimensions of the plot. 到目前为止,我已经能够成功创建光盘并将其放置在绘图上,但是我的问题来自于取决于绘图尺寸的拉伸效果。

Here are the function I've used to create the disc so far: 到目前为止,这是我用来创建光盘的功能:

# A circle function to draw a circle (pulled form another stackoverflow page)

circleFun <- function(center=c(0,0), diameter=1, npoints=100, start=0, end=2, filled=TRUE){
  tt <- seq(start*pi, end*pi, length.out=npoints)
  df <- data.frame(
    x = center[1] + diameter / 2 * cos(tt),
    y = center[2] + diameter / 2 * sin(tt)
  )
  if(filled==TRUE) { #add a point at the center so the whole 'pie slice' is filled
    df <- rbind(df, center)
  }
  return(df)
}

# and my function to create a secchi disc
secchiDisc = function(x,y,diameter = 1){
  quarterCircle1 = circleFun(c(x,y),diameter = diameter, start=0, end=0.5)
  quarterCircle3 = circleFun(c(x,y),diameter = diameter, start=1, end=1.5)
  fullCircle = circleFun(c(x, y), diameter, start=0, end=2)
  polygon(quarterCircle1$x,quarterCircle1$y,col="black")
  polygon(quarterCircle3$x,quarterCircle3$y,col="black")
  polygon(fullCircle$x,fullCircle$y)
}

# make a plot to show what it looks like
par(mar = c(5, 4, 4, 2) + 0.1)
plot(0,0,pch = "")
secchiDisc(0,0)

在此处输入图片说明

# create data frame 
data = as.data.frame(list(Year = 1970:2015,
                          Depth = rnorm(46,3,1)))

# and create a time series plot showing changes in depth over time
plot(data$Year,data$Depth,pch="",ylim = c(7,0))
for(i in 1:nrow(data)){
  secchiDisc(data$Year[i],data$Depth[i])
}



So here is how it looks when plotting with a time series: 因此,这是按时间序列进行绘制时的外观: 在此处输入图片说明

And obviously I can just stretch the plot horizontally until it cleans up, but I was wondering if anyone out there has any suggestions on how to automatically get the disc to re-size based on the plot? 显然,我可以水平拉伸图直到清理干净,但是我想知道是否有人对如何根据图自动调整光盘大小有任何建议? 在此处输入图片说明

I've tried to customize the circle functions to allow for a stretch effect, but to no avail. 我尝试自定义圆形功能以允许拉伸效果,但无济于事。 I think one of the problems with the 'stretch effect' approach is that I still want the disc to appear circular, but I couldn't get the diameter of the circle to change independently of the x or y dimension. 我认为“拉伸效果”方法的问题之一是,我仍然希望光盘显示圆形,但是我无法使圆的直径独立于x或y尺寸而变化。

Another thought I had was to save a blank plot of the secchi disc as a png file and try to plot the imported file. 我的另一个想法是将secchi光盘的空白图另存为png文件,然后尝试绘制导入的文件。 Thoughts on this approach? 对这种方法有何想法?

Thanks for any help. 谢谢你的帮助。

I think I have a solution. 我想我有解决办法。 If not, I must be very close. 如果没有,我一定很亲近。 The problem is that in your function, the diameter is the same for the x-axis and the y-axis, independently of range of data. 问题在于,在您的函数中,x轴和y轴的直径相同,而与数据范围无关。 Said differently, the range of the Years axis is 45 and the range of the Depth axis is ~5. 换句话说,“年”轴的范围是45,而“深度”轴的范围是〜5。 When you try to apply the same diameter in units to both axis, the shape of the circle is deformed. 当您尝试将相同的直径单位应用到两个轴时,圆的形状会变形。 My solution is to calculate a ratio of the ranges of the x-axis and y-axis. 我的解决方案是计算x轴和y轴范围的比率。 The ratio is then applied to the sin line in circleFun . 然后将该比率应用于circleFunsin线。 I'm not sure if the ratio should be divided by sqrt(2) but it works. 我不确定该比率是否应除以sqrt(2)但它可以工作。 Also, you should not resize your plotting window manually after plotting the chart. 另外,在绘制图表之后,您不应该手动调整打印窗口的大小。 use win.graph in windows or quartz() in mac before the plot. 在绘图前在Windows中使用win.graph或在Mac中使用quartz()

    # A circle function to draw a circle (pulled form another stackoverflow page)

circleFun <- function(center=c(0,0), diameter=1, npoints=100, start=0, end=1, filled=TRUE,ratio=1){
  tt <- seq(start*pi, end*pi, length.out=npoints)
  df <- data.frame(
    x = center[1] + diameter / 2 * cos(tt),
    y = center[2] + diameter/ratio / 2 * sin(tt)
  )
  if(filled==TRUE) { #add a point at the center so the whole 'pie slice' is filled
    df <- rbind(df, center)
  }
  return(df)
}

# and my function to create a secchi disc
secchiDisc = function(x,y,diameter = 1,ratio=1){
  quarterCircle1 = circleFun(c(x,y),diameter = diameter, start=0, end=0.5,ratio=ratio)
  quarterCircle3 = circleFun(c(x,y),diameter = diameter, start=1, end=1.5,ratio=ratio)
  fullCircle = circleFun(c(x, y), diameter, start=0, end=2,ratio=ratio)
  polygon(quarterCircle1$x,quarterCircle1$y,col="black")
  polygon(quarterCircle3$x,quarterCircle3$y,col="black")
  polygon(fullCircle$x,fullCircle$y)
}

data = as.data.frame(list(Year = 1970:2015,
                          Depth = rnorm(46,3,1)))

xx <-diff(range(data$Year))
yy <-diff(range(data$Depth))
ratio=(xx/yy)/sqrt(2)
plot(data$Year,data$Depth,pch="")
for(i in 1:nrow(data)){
  secchiDisc(data$Year[i],data$Depth[i],diameter = 1.5,ratio=ratio)
}

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM