【问题标题】:Plotting animated exchange (plotting directional edges)绘制动画交换(绘制方向边)
【发布时间】:2013-03-08 03:49:32
【问题描述】:

我曾经在航运交易中看到this plot (LINK)。我从事对话交流工作,并认为使用 R 映射这种交流可能会很有趣。

这是一个更大的问题,但我认为它可能对整个社区有用。

假设我们有 7 个人围坐在这样的桌子旁:

我已经录制了对话交流的演讲者谈话和听众听到的声音。我用这种信息创建了一个虚拟的 data.frame。这是头:

  speaker receiver duration speaker.x speaker.y receiver.x receiver.y
1       D        A       16     0.626     0.163      0.755      0.741
2       E        D        3     0.391     0.161      0.626      0.163
3       A        B       25     0.755     0.741      0.745      0.517
4       B        E        6     0.745     0.517      0.391      0.161
5       B        C       45     0.745     0.517      0.737      0.251
6       E        F       37     0.391     0.161      0.258      0.285

我想创建动画箭头(从扬声器到接收器),由扬声器着色并加权(时间/持续时间和长度和/或厚度)并以与运输数据相同的方式动画(行number 是语音发生的顺序)。我认为也许动画包在这里可能有用但没有任何线索。也许目前 R 不可能做到这一点(正如 Ben Schmidt 的声明所表明的那样,“我一直希望我可以放弃 ArcGIS 来进行我的下一个地图项目,并将所有内容保留在 R--I在这次经历之后,我不相信这是可能的”)。

我认为许多领域的许多人都可以使用这种交流映射,恰好我对对话交流感兴趣。最终我会在光栅图像上绘制它,但这是最简单的部分。

这是到目前为止的数据和图表。

#the data
the_table <- data.frame(
    xmin = .3,
    xmax = .7,
    ymin = .2,
    ymax = .8
)

points <- structure(list(x = c(0.754594594594595, 0.744864864864865, 0.736756756756757, 
    0.626486486486486, 0.391351351351351, 0.258378378378378, 0.261621621621622
    ), y = c(0.741172932330827, 0.517052631578947, 0.250706766917293, 
    0.163007518796992, 0.161383458646617, 0.284812030075188, 0.494315789473684
    )), .Names = c("x", "y"))


mapping <- data.frame(person=LETTERS[1:7], points)

set.seed(10)
n <- 120
dat <- data.frame(id = 1:n, speaker=sample(LETTERS[1:7], n, TRUE),
     receiver=sample(LETTERS[1:7], n, TRUE),
    duration=sample(1:50, n, TRUE)
)
dat <- dat[as.character(dat$speaker)!=as.character(dat$receiver), ]

dat <- merge(merge(dat, mapping, by.x=c("speaker"), by.y=c("person"), sort=FALSE), 
    mapping, by.x=c("receiver"), by.y=c("person"), sort=FALSE)
names(dat)[5:8] <- c("speaker.x", "speaker.y", "receiver.x", "receiver.y")
dat <- dat[order(dat$id), c(2, 1, 4:8)]
rownames(dat) <- NULL

#the plot
ggplot() +
    geom_point(data=mapping, aes(x=x, y=y), size=10) +
    geom_text(data=mapping, aes(x=x, y=y, label=as.character(person)), 
        color="blue") +
    ylim(-.2, 1.2) + xlim(-.2, 1.2) + 
    geom_rect(data=the_table, aes(xmax = xmax, xmin=xmin, 
        ymin=ymin, ymax = ymax), fill="gray80")

我没有嫁给 ggplot2,但我偏爱它,而且似乎很多这类情节都使用 ggplot2。

【问题讨论】:

  • 你可能不是,但我嫁给了 ggplot2 :)
  • 试试igraph
  • @Gary I know about igraph 但据我所知,它不做动画。
  • 动画从何而来?一次只有一个人说话,还是每个人都有开始和结束时间speech
  • @Marius 使用动画包在 R 中拼接帧真的很容易......如果您能够从 R 中制作图像,则无需走出 R。

标签: r graphing animated


【解决方案1】:

使用动画包和geom_segment 这是相当直接的

到目前为止,我唯一的问题是让尺寸合理地工作

我已将通话 data.frame 保存为 talking

library(animation)
library(RColorBrewer)
library(grid)         ## for arrow
library(ggplot2)      
# scale the duration (not ideal)
talking$scale_duration <-scale(talking$duration, center = FALSE)
# ensure that we have different colours for each speaker

ss <- levels(talking$speaker)

speakerCol <- scale_colour_manual(values = setNames(brewer.pal(n=length(ss), 'Set2' ), ss), guide = 'none')

# the base plot with the table and speakers (and `talking` base dataset)
base <- ggplot(data = talking, aes(colour = speaker)) +
  geom_point(data=mapping, aes(x=x, y=y), size=10, inherit.aes = FALSE) +
  geom_text(data=mapping, aes(x=x, y=y, label=as.character(person)), 
    inherit.aes = FALSE, color="blue") +
  ylim(-.2, 1.2) + xlim(-.2, 1.2) + 
  geom_rect(data=the_table, aes(xmax = xmax, xmin=xmin, 
      ymin=ymin, ymax = ymax), fill="gray80", inherit.aes = FALSE) +
  speakerCol
 oopt <- ani.options(interval = 0.5)

# a function to create the animation


pp <- function(){
  print(base)
  interval = ani.options("interval")
  for(n in rep(seq_along(talking$duration), each = talking$duration))){
    # a segment for each row
    tn <- geom_segment(aes(x= speaker.x, y= speaker.y, xend = receiver.x, yend = receiver.y), arrow = arrow(), 
                       data =talking[n, ,drop = FALSE])
    print(base + tn)
    ani.pause()
  }
}

使用saveGIF(pp(), interval = 0.1)导出GIF动画等

【讨论】:

  • 不错的答案。非常彻底。动画比我预期的要容易。谢谢你。现在我将开始处理一些更复杂的情况,但我只需要玩一会儿。
  • @Tyler -- 这也比我预期的要容易!
  • 我认为您的动画每次交换显示一帧,而不是“实时”显示每一帧的长度为该交换的 duration 变量。你是不是想在某处给ani.pause(interval)打电话?
  • @spacedman,说得好。正在制作持续时间=大小。编辑得更好(我希望,未经测试)
  • @mnel 是否需要这条线oopt &lt;- ani.options(interval = 0.5)
猜你喜欢
  • 2012-10-24
  • 1970-01-01
  • 1970-01-01
  • 2013-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多