矢量场可视化 R

18

我有一个包含很多行的大型文本文件。每一行对应一个向量。 以下是每一行的例子:

        x           y               dx              dy
99.421875   52.078125   0.653356799108  0.782479314511

前两列是向量起点的坐标。后两列是坐标增量(终点减去起点)。 我需要制作这个向量场的图片(所有向量在一个图片上)。 我该怎么做呢? 谢谢


3
添加类似于arrows(DF[,1], DF[,2], DF[,1] + DF[,3], DF[,2] + DF[,4])的内容。请参阅?arrows了解更好的控制方式。尽管假设会有更好的答案。 - tim riffe
2
@timriffe,你应该将它添加为答案,因为原帖作者可能会喜欢一个“基础”解决方案,作为“ggplot2”解决方案的替代。 - plannapus
4个回答

41
如果数据量很大(问题中说“大文件”),绘制单个向量可能无法得到一个非常易读的图。这里有另一种方法:矢量场描述了在平面上绘制的形状的变形方式;将它应用于白噪声图像。
vector_field <- function(
  f,  # Function describing the vector field
  xmin=0, xmax=1, ymin=0, ymax=1,
  width=600, height=600,
  iterations=50,
  epsilon=.01,
  trace=TRUE
) {
  z <- matrix(runif(width*height),nr=height)
  i_to_x <- function(i) xmin + i / width  * (xmax - xmin)
  j_to_y <- function(j) ymin + j / height * (ymax - ymin)
  x_to_i <- function(x) pmin( width,  pmax( 1, floor( (x-xmin)/(xmax-xmin) * width  ) ) )
  y_to_j <- function(y) pmin( height, pmax( 1, floor( (y-ymin)/(ymax-ymin) * height ) ) )
  i <- col(z)
  j <- row(z)
  x <- i_to_x(i)
  y <- j_to_y(j)
  res <- z
  for(k in 1:iterations) {
    v <- matrix( f(x, y), nc=2 )
    x <- x+.01*v[,1]
    y <- y+.01*v[,2]
    i <- x_to_i(x)
    j <- y_to_j(y)
    res <- res + z[cbind(i,j)]
    if(trace) {
      cat(k, "/", iterations, "\n", sep="")
      dev.hold()
      image(res)
      dev.flush()
    }
  }
  if(trace) {
    dev.hold()
    image(res>quantile(res,.6), col=0:1)
    dev.flush()
  }
  res
}

# Sample data
van_der_Pol <- function(x,y, mu=1) c(y, mu * ( 1 - x^2 ) * y - x )
res <- vector_field(
  van_der_Pol,
  xmin=-3, xmax=3, ymin=-3, ymax=3,
  width=800, height=800,
  iterations=50,
  epsilon=.01
)
image(-res)

Van der Pol attractor你可能需要对结果应用一些图像处理,以使其更易读。

image(res > quantile(res,.6), col=0:1)

二值化后

在您的情况下,向量场不是由一个函数描述的:您可以使用最近邻居的值或一些二维插值(例如来自akima包)。


这是一个很酷的方法,但我认为它不太适合大型数据集:是的,最终输出非常易读,但是耗时过长。我不明白从随机矩阵开始并添加循环只是为了拥有一个可视化设备的意义所在。 - epsilone

18
使用ggplot2,您可以做出如下图所示的内容:
library(grid) 
df <- data.frame(x=runif(10),y=runif(10),dx=rnorm(10),dy=rnorm(10))
ggplot(data=df, aes(x=x, y=y)) + geom_segment(aes(xend=x+dx, yend=y+dy), arrow = arrow(length = unit(0.3,"cm")))

enter image description here

这段内容几乎直接摘自geom_segment帮助页面

1
你知道是否有类似的方法可以使用 R 创建 3D 向量场吗? - gsimard
嗨,我想知道是否也可以使用具有几何字段的sf对象来完成这个操作,而不是使用X和Y列。 - Pablo Herreros Cantis

5

好的,这里是一个基本解决方案:

DF <- data.frame(x=rnorm(10),y=rnorm(10),dx=runif(10),dy=runif(10))
plot(NULL, type = "n", xlim=c(-3,3),ylim=c(-3,3))
arrows(DF[,1], DF[,2], DF[,1] + DF[,3], DF[,2] + DF[,4])

3

以下是来自pracma包的R-Help示例。

library(pracma)
f <- function(x, y) x^2 - y^2
xx <- c(-1, 1); yy <- c(-1, 1)
vectorfield(f, xx, yy, scale = 0.1)
for (xs in seq(-1, 1, by = 0.25)) {
    sol <- rk4(f, -1, 1, xs, 100)
    lines(sol$x, sol$y, col="darkgreen")
}

你也可以使用 Quiver。
library(pracma)
xyRange <- seq(-1*pi,1*pi,0.2)
temp <- meshgrid(xyRange,xyRange)
u <- sin(temp$Y)
v <- cos(temp$X)
plot(range(xyRange),range(xyRange),type="n",xlab=expression(frac(d*Phi,dx)),ylab=expression(d*Phi/dy))
quiver(temp$X,temp$Y,u,v,scale=0.5,length=0.05,angle=1)

3
我实在是想不明白pracma函数在做什么。 - Andres Mejia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接