矢量化:使用geom_path绘制多个轮廓

3
我正在编写代码以创建多个轮廓数据集。 我的步骤如下:
  1. 使用

    T<-runif()

    生成原始数据。

  2. 编写描述由参数函数描述的轮廓的函数:

    • x<-function(t)
    • y<-function(t)
  3. 将实数向量x,y转换为复数x + 1i * y

  4. 对数据应用一个复杂函数,例如,

    sin

  5. 将实部和虚部提取到一组实数中

    fx,fy

  6. 绘制配对项

    geom_path(x = fx,y = fy)

  7. 将它与颜色向量编码

我每次想要绘制轮廓时都会重复使用这些代码,但是我想矢量化它,以便可以最小化我的代码重复。 我该怎么做?
以下是示例:
  #Create data

  #the parameter:
  T<-sort(runif(100,min=-1, max=1))


  #x(t), y(t)
  xt.hor<-function(t,c){
    return(c)
  }
  yt<-function(t,scale){
    return (scale*t)
  }


  X1<-mapply(xt.hor,T,c=-10)
  # X2, X3, X4
  X5<-mapply(xt.hor,T,c=10)

  YHor<-mapply(yt,T,scale=10)

  df1<-data.frame(x1=X1,
                  #x2,x3,x4,
                  x5=X5,yh=YHor)


  #convert to complex numbers:

  toComplex<-function(x,y){complex(real=x,imaginary=y)}

  z1<-mapply(toComplex,df1$x1,y=df1$yh)
  #z2, z3, z4
  z5<-mapply(toComplex,df1$x5,y=df1$yh)

  fz1<-sapply(z1,sin)
  #fz2,fz3,fz4
  fz5<-sapply(z5,sin)

  fx1<-sapply(fz1,Re)
  #fx2,fx3,fx4
  fx5<-sapply(fz5,Re)

  fy1<-sapply(fz1,Im)
  #fy2,fy3,fy4
  fy5<-sapply(fz5,Im)

  df2<-data.frame(fx1=fx1,fy1=fy1,
                  #curve2, curve 3, curve 4
                  fx5=fx5,fy5=fy5)

  RedOrgVector<-c('#fd8d3c','#fc4e2a','#e31a1c','#bd0026','#800026')

  p <- ggplot(data = df2)

  p+xlim(c(-10,10))+ylim(c(-10,10))+
    geom_path(x=fx1,y=fy1,size=.75,color=RedOrgVector[1],linetype=1)+
    #curve2, curve3, curve4
    geom_path(x=fx5,y=fy5,size=.75,color=RedOrgVector[5],linetype=1)

3
顺便提一下,toComplex 是向量化的,不需要使用 mapply - baptiste
3
据我所知,对于下面的sapply行,情况也是如此。 - baptiste
1个回答

2
这里有一种使用tidyverse的方法,大部分代码可以压缩成一个函数,将提供的数据构建和转换为ggplot2喜欢的格式。 generate_curve函数实现了这个目的。它需要一个输入向量和参数(c、比例尺和曲线数量),并返回一个tibble(高级数据框),其中包含x、y和曲线编号。
要获得多条曲线,可以通过生成多个输入向量(通过rerun),并使用purrrmapplygenerate_curve函数映射到每个向量。在这种情况下,我使用purr中的pmap_df,它将一个函数映射到一个输入列表,并返回一个数据框。
library(tidyverse)

generate_curve <- function(data, c, scale, n) {

  tibble(X = c,
         YHor = scale*data,
         z = complex(real = X, imaginary = YHor),
         fz = sin(z),
         fx = Re(fz),
         fy = Im(fz)) %>% 
    select(fx, fy) %>% 
    mutate(row = row_number()) %>% 
    gather(group, value, -row) %>% 
    extract(group, "var", regex = "f(\\w)") %>% 
    spread(var, value) %>% 
    mutate(curve = n) %>% 
    select(-row)
}

list <- rerun(4, sort(runif(100, min = -1, max = 1)))
cs <- c(10,5,-5,-10)
scale <- rep(10,4)
length <- seq_along(list)

curves <- pmap_df(list(list,cs,scale,length), generate_curve)

RedOrgVector <- c('#fd8d3c','#fc4e2a','#e31a1c','#bd0026','#800026')

ggplot(curves, aes(x = x, y = y, group = factor(curve))) +
  geom_path(aes(color = factor(curve)), linetype = 1) +
  scale_color_manual(values = setNames(RedOrgVector, c(1:5))) +
  xlim(c(-10,10)) +
  ylim(c(-10,10))

enter image description here


这是函数式编程吗?我不知道“R”可以这样工作!太棒了! - GFauxPas
我正在跟随你的大部分代码,但请解释一下“spread(var, value)”是什么意思。 - GFauxPas
spread函数将var的不同取值转换为列,并使用value的值填充每一行。更多详情请参考:https://blog.rstudio.org/2014/07/22/introducing-tidyr/ - Jake Kaupp

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