如何绘制每条线之间具有特定距离的图形

时间:2016-04-06 10:52:33

标签: r

实际上我试图绘制一个数字,但它会放置并显示彼此之间的所有列(线),因此它不具代表性。我尝试制作模拟数据并向您展示我如何绘制它,并向您展示我想要的内容

我不知道如何制作如下所示的数据,但我在这里做什么

set.seed(1)
M <- matrix(rnorm(20),20,5)
x <- as.matrix(sort(runif(20, 5.0, 7.5)))
df <- as.data.frame(cbind(x,M))

在制作数据框之后,我将通过融合并使用ggplot来绘制所有列与第一列的关系

require(ggplot2)
require(reshape)
dff <- melt(df ,  id.vars = 'V1')
b <- ggplot(dff, aes(V1,value)) + geom_line(aes(colour = variable))

我想在每一行之间有特定的距离(在这种情况下我们有6),如下所示。在一个维度,它是V1,在另一个维度,它是列的数量。我不关心这个功能,我只想要照片

3 个答案:

答案 0 :(得分:8)

此解决方案使用rgl并生成此图:

enter image description here

它使用这个接受3个参数的函数:

  • dfdata.frame就像上面的“M”一样
  • x:x轴的numeric vector (or a 1-col data.frame`)
  • cols :( optionnal)要重复的颜色矢量。如果缺少,则绘制黑线

这是功能:

nik_plot <- function(df, x, cols){
  require(rgl)
  # if a data.frame is
  if (is.data.frame(x) && ncol(x)==1)
    x <- as.numeric(x[, 1])
  # prepare a vector of colors
  if (missing(cols))
    cols <- rep_len("#000000", nrow(df))
  else
    cols <- rep_len(cols, nrow(df))
  # initialize an empty 3D plot
  plot3d(NA, xlim=range(x), ylim=c(1, ncol(df)-1), zlim=range(df), xlab="Mass/Charge (M/Z)", ylab="Time", zlab="Ion Spectra", box=FALSE)
  # draw lines, silently
  silence_please <- sapply(1:ncol(df), function(i) lines3d(x=x, y=i, z=df[, i], col=cols[i])) 
}

请注意,您可以从函数中删除require(rgl),并在脚本中的某处删除library(rgl),例如在开头。

如果您没有安装rgl,则install.packages("rgl")

默认情况下,黑色线条可能会产生一些莫尔纹效果,但重复的调色板会更糟。这可能是依赖于大脑的。单一颜色也可以避免引入人造尺寸(和强烈的尺寸)。

以下示例:

# black lines
nik_plot(M, x)
# as in the image above
nik_plot(M, x, "grey40")
# an unreadable rainbow
nik_plot(M, x, rainbow(12))

可以使用鼠标导航3D窗口。

你还需要其他东西吗?

修改

您可以使用下面的功能构建第二个绘图。您的数据范围非常大,我认为每条线向上移动的整个想法都会阻止y轴具有可靠的比例。这里我已经对所有信号进行了归一化(0 <=信号&lt; = 1)。参数gap也可以用来玩这个。我们可以断开这两种行为,但我认为这很好。请尝试gap的不同值,并参阅下面的示例。

  • dfdata.frame就像上面的“M”一样
  • x:x轴的numeric vector (or a 1-col data.frame`)
  • cols :( optionnal)要重复的颜色矢量。如果缺少,则绘制黑线
  • gap:各行之间的差距因素
  • more_gap_each:每n行,就会产生更大的差距......
  • more_gap_relative:...并且gap x more_gap_relative

这是功能:

nik_plot2D <- function(df, x, cols, gap=10, more_gap_each=1, more_gap_relative=0){
  if (is.data.frame(x) && ncol(x)==1)
    x <- as.numeric(x[, 1])

  # we normalize ( 0 <= signal <= 1)
  df <- df-min(df)
  df <- (df/max(df))
  # we prepare a vector of colors
  if (missing(cols))
    cols <- rep_len("#00000055", nrow(df))
  else
    cols <- rep_len(cols, nrow(df))
  # we prepare gap handling. there is probably more elegant
  gaps <- 1
  for (i in 2:ncol(df))
    gaps[i] <- gaps[i - 1] + 1/gap + ifelse((i %% more_gap_each) == 0, (1/gap)*more_gap_relative, 0)
  # we initialize the plot
  plot(NA, xlim=range(x), ylim=c(min(df), 1+max(gaps)), xlab="Time", ylab="", axes=FALSE, mar=rep(0, 4))
  axis(1)
  # finally, the lines
  silent <- lapply(1:ncol(df), function(i) lines(x, df[, i] + gaps[i], col=cols[i]))
}

我们可以使用它(默认):

nik_plot2D(M, x) # gap=10

你得到这个情节:

enter image description here

或:

nik_plot2D(M, x, 50)

enter image description here

或者,用颜色:

nik_plot2D(M, x, gap=20, cols=1:3)
nik_plot2D(M, x, gap=20, cols=rep(1:3, each=5))

或仍然有颜色,但间隙较大:

nik_plot2D(M, x, gap=20, cols=terrain.colors(10), more_gap_each = 1, more_gap_relative = 0) # no gap by default
nik_plot2D(M, x, gap=20, cols=terrain.colors(10), more_gap_each = 10, more_gap_relative = 4) # large gaps every 10 lines
nik_plot2D(M, x, gap=20, cols=terrain.colors(10), more_gap_each = 5, more_gap_relative = 2) # small gaps every 5 lines

enter image description here

答案 1 :(得分:5)

正如其他人所指出的,你的数据有很大的峰值,你不清楚是否要允许某些曲线重叠,

enter image description here

m <- read.table("~/Downloads/M.txt", head=T)

fudge <- 0.05
shifty <- function(m, fudge=1){
  shifts <- fudge * max(abs(apply(m, 2, diff))) * seq(0, ncol(m)-1)
  m + matrix(shifts, nrow=nrow(m), ncol=ncol(m), byrow=TRUE)
}
par(mfrow=c(1,2), mar=c(0,0,1,0))
cols <- colorRampPalette(blues9[4:9])(ncol(m))
matplot(shifty(m), t="l", lty=1, bty="n", yaxt="n", xaxt="n", ylab="", col=cols)
title("no overlap")
matplot(shifty(m, 0.05), t="l", lty=1, bty="n", yaxt="n", xaxt="n", ylab="", col=cols)
title("some overlap")

或者,在计算曲线之间的偏移之前,可以使用一些异常值/峰值检测方案对其进行滤波,

library(outliers)

shifty2 <- function(m, outliers = 10){
  tmp <- m
  for(ii in seq_len(outliers)) tmp <- rm.outlier(tmp, median = TRUE)
  shifts <- max(abs(apply(tmp, 2, diff))) * seq(0, ncol(m)-1)
  m + matrix(shifts, nrow=nrow(m), ncol=ncol(m), byrow=TRUE)
}

matplot(shifty2(m), t="l", lty=1, bty="n", yaxt="n", xaxt="n", ylab="", col=cols)

enter image description here

(可能有很好的算法来决定删除哪些点,但我不知道它们)

答案 2 :(得分:0)

对于3D绘图,我更喜欢rgl包。这应该接近您期望的解决方案 每次扫描的颜色每三分之一就会发生变化。

library(rgl)
M<-read.table("M.txt", sep="\t", header = TRUE, colClasses = "numeric")
x<-read.table("x.txt", sep="\t", header = TRUE)
n<-ncol(M)
M[M<1]<-1
plot3d(x='', xlim=range(x$Time), ylim=c(1, n), zlim=(range(M)), box=FALSE)
sapply(seq(1,n), function(t){lines3d(x$Time, y=t*10, z=(M[,t])/10000, col=t/3+1)})
title3d(xlab="scan", ylab="time", zlab="intensity")
title3d(main ="Extracted Spectra Subset")
axes3d()
#axis3d(edge="x")
#axis3d(edge="y")
#axis3d(edge="z")

数据点的幅度存在巨大差异,我需要扩展一些因素来制作可读的图形。强度从0到近1,000,000,从而扭曲图形。以ln为标准化,但情节变得难以理解。