bind merge r 和join_[R] 制作梅西和C罗进球数的quot;追赶动画quot; - ggplot2 + gifski

db7861b2856ac7c882c98db645220604.png

效果如下:

1d32d2c59c56e0f3a44043f26f7cd892.png
数据可视化 - 梅西 vs C罗https://www.zhihu.com/video/1084910827596804096
786b4b064f93af3c42a21538fa8ff95d.png
数据可视化 - 8大射手进球趋势https://www.zhihu.com/video/1084910854461321216

制作过程分为3个步骤:

  1. 处理数据
  2. ggplot2创建图像帧
  3. save_gif逐帧打包生成gif文件

使用的packages:

library(dplyr)
library(ggplot2)
library(ggthemes)
library(gifski)

数据处理

gen_df <- function() {mdf <- read.csv('messi.csv')rdf <- read.csv('ronaldo.csv')alldate = c(mdf$date, rdf$date) %>% unique %>% sort %>% data.frame(date = .)tf <- function(d, name) {merge(d, alldate, all = T) %>%{.[is.na(.)] = 0; .$var = name; .} %>%dplyr::mutate(value = cumsum(n))}mdf <- tf(mdf, '梅西')rdf <- tf(rdf, 'C罗')bind_rows(mdf, rdf) %>%dplyr::arrange(desc(value)) %>%dplyr::arrange(date)
}

数据处理之前要列出制作动画的关键点:

  • 两人的point和label要同时显示(两人比赛可能不在同一天)
  • 在两人的label重合的时候,进球数多的人的label要显示在上面

因此就需要将两人的比赛日做union再和两人的data做merge,将缺失的日期补上,再用cumsum()对进球数做累加

alldate = c(mdf$date, rdf$date) %>% unique %>% sort %>% data.frame(date = .)
tf <- function(d, name) {merge(d, alldate, all = T) %>%{.[is.na(.)] = 0; .$var = name; .} %>%dplyr::mutate(value = cumsum(n))
}

然后将两人的数据合并,但考虑上面说的第2点要求,还需要将数据排序做调整:

bind_rows(mdf, rdf) %>%dplyr::arrange(desc(value)) %>%dplyr::arrange(date)

先把value(进球数)做升序排序,再按date(日期)做降序排序

至此数据处理完毕


ggplot2创建图像帧

gen_plt <- function(df, date_end) {gdf <- filter(df, date <= date_end)f = floor(max(gdf$value) / 100)hlines = if (f > 0) seq(100, f * 100, 100) else fwindowsFonts(myFont = windowsFont("微软雅黑"))ggplot(data = gdf,aes(x = date,y = value,color = var,label = paste0(var, '(', value, ')'))) +geom_path() +scale_x_date(breaks = seq.int(df$date[1], df$date[nrow(df)], '4 months'),date_labels = "%Y-%m",limits = c(df$date[1], df$date[nrow(df)] + 150)) +geom_point(data = filter(gdf, date == date_end),size = 2) +geom_text(data = filter(gdf, date == date_end),fontface = 'bold',hjust = 0,vjust = c(-.2, .2),nudge_x = 30,size = 3.5,check_overlap = T) +geom_hline(yintercept = hlines,linetype = 2) +scale_color_manual(values = c('chocolate', 'blue1')) +theme_fivethirtyeight() +theme(text = element_text(family = 'myFont'),axis.text.x = element_text(angle = -30, hjust = 0),legend.position = "none",plot.title = element_text(face = "bold", color = '#334433'),plot.subtitle = element_text(face = "bold", size = 14, color = '#667766'),plot.caption = element_text(hjust = 0, size = 10, face = "bold.italic", color = '#556677')) +labs(x = "",y = "",title = "总进球数对比(2009 ~ 2019年): 梅西 vs 罗纳尔多",subtitle = filter(df, date == date_end)$date %>% unique,caption = 'Made by 老白Walt')
}

代码比较多,因为ggplot2如果不做任何配置,效果是比较差的

其中关键的几个是geom_path画线,geom_point画点,geom_text画文字

需要说明一下的是geom_text中的两个参数:

check_overlap: 如果设定为T(TRUE),则在文本有重叠的情况下先绘制的会盖掉后绘制的

vjust: 通过调整文本的纵向坐标,拉开两个文本的间距,可以尽量避免overlap

另外GIF文件就是将很多张图片串联起来生成动画,所以这里定义了一个生成ggplot object的函数,用来将每个比赛日的图片都生成出来


save_gif逐帧打包生成gif文件

gen_gif <- function(df, filename, width = 1280, height = 720, res = 144) {dates = df$date %>% unique %>% sortcnt = length(dates)save_gif({print('Processing...')for (i in 1:cnt) {g <- gen_plt(df, dates[i])print(paste(i, 'of', cnt))print(g)}for (i in 1:20) {print(paste(i, 'of', 20))print(g)}},gif_file = filename,width = width,height = height,res = res,delay = 0.1)
}df <- gen_df()
gen_gif(df, 'messi_vs_ronaldo.gif')

这里就是遍历date,逐个生成图片:

g <- gen_plt(df, dates[i])

并打印输出到save_gif

print(g)

save_gif会帮你生成最终的gif文件

它的不足之处是生成时间比较长


第二个视频有一些不一样的地方,我选取了最近10年进球最多的8位球员来做动画,如果union所有人的date会有近10000项(即10000帧),对GIF来说就是灾难

退而求其次,将date都转为week即缩减到384帧,完成动画毫无压力


本专栏只生产干货,喜欢请关注
数据及可视化​zhuanlan.zhihu.com
2cd9d67671878f656204bd66a45fbd3c.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/441538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【CodeForces-1041C】Coffee Break(贪心,STL,set二分维护,题意难,有坑,SJ题,构造)(知识点总结)

题干&#xff1a; Recently Monocarp got a job. His working day lasts exactly mm minutes. During work, Monocarp wants to drink coffee at certain moments: there are nn minutes a1,a2,…,ana1,a2,…,an, when he is able and willing to take a coffee break (for th…

盐务街属于一环吗_郑州步入“五环”时代,最早的“一环”原来是这里

近日&#xff0c;郑州“五环路”建设最新进展受到广泛关注。当郑州步入“五环”时代时&#xff0c;你是否想过郑州的最早的“一环”在哪里?来跟随记者的讲解&#xff0c;来一场时空逆行穿梭之旅&#xff0c;从历史深处寻找郑州最早的“一环”。△郑州五环示意图◆郑州现代“一…

C++ 输入输出加速挂(ACM竞赛常用)

好多种版本&#xff0c;今天给出其中之一&#xff0c;也是比较快的一种。 int read() {char ch getchar();int num 0;bool fl 0;for(; !isdigit(ch); ch getchar())if (ch-) fl 1;for(; isdigit(ch); ch getchar())num (num<<1)(num<<3)ch-48;if(fl) num …

oracle中那个日期怎么相减_oracle数据库中日期加减函数

1.oracle中当前系统时间加减用法select add_months(sysdate, 12) "NEW YEAR" from dual; /**系统时间12个月后的时间**/select extract(month from sysdate) "This Month" from dual; /**获取系统时间所在月份**/select (sysdate 1) "NEW DATE"…

【CodeForces - 1041D】Glider (枚举起点,双指针 或 二分终点,思维)(知识点总结)

题干&#xff1a; A plane is flying at a constant height of hh meters above the ground surface. Lets consider that it is flying from the point (−109,h)(−109,h) to the point (109,h)(109,h) parallel with OxOx axis. A glider is inside the plane, ready to s…

duilib vs2015 安装_FFmpeg视频播放器开发-FFmpeg简介与项目环境搭建(一)

前言&#xff1a;视频开发库有很多&#xff0c;例如微软的DirectShow&#xff1b;开源库OpenCV&#xff0c;当然OpenCV主要是图像处理&#xff0c;视频部分还是用的ffmpeg, 而且无法解码音频&#xff1b;SDL&#xff1b;大华和海康都有自己的库等等。音视频属于流媒体领域&…

【洛谷 - U43391】不是0-1背包的暴力AC(思维,二分,可转化为二元组问题,复习暴力dfs总结)

题干&#xff1a; https://www.luogu.org/problemnew/show/U43391 自01背包问世之后&#xff0c;小A对此深感兴趣。一天&#xff0c;小A去远游&#xff0c;却发现他的背包不同于01背包。 小A的背包最多能装W的价值 现有n件物品&#xff0c;分别为v1,v2,v3……vn 问如何存放物…

windowsthinpc虚拟内存_windows thin pc如何开启windows功能

没有“\DS\”目录 (子目录)没有“\Packages\”目录(子目录)没有“\FeaturePack\”目录(子目录)没有“\LangPacks\"目录(子目录)未找到“winemb-premiumcodecs-dolby-ac3-audioencoder.cab”未找到“WinEmb-PremiumCodecs-MPEG2andDolbyDecoder.cab”未找到“WinEmb-Premiu…

【牛客 - 185F】 假的数学游戏(斯特林公式,大数Java打表)

题干&#xff1a; 输入描述: 第一行&#xff1a;一个整数X 输出描述: 第一行&#xff1a;一个整数N 示例1 输入 复制 7 输出 复制 10 备注: 每个测试点所对应的X满足&#xff1a;第i个测试点输入的值为第i-1个测试点输入的值乘以10再加上7。特别的&#xff0c;第一个…

js怎么调用wasm_对于WebAssembly编译出来的.wasm文件js如何调用

WebAssembly也叫浏览器字节码技术 这里就不过多的解释了网上很多介绍主要是让大家知道在js里面如何调用执行它&#xff0c;我之前看WebAssemblyAPI时候反正是看得一脸懵逼也是为了大家能更快的入手这个比较新的技术吧这边写的一个dom是官方推荐的c/c编译的c代码1 int add (int …

*【HDU - 6333】Problem B. Harvest of Apples (莫队,逆元,组合数学)(这样预处理正确吗?)

题干&#xff1a; There are nn apples on a tree, numbered from 11 to nn. Count the number of ways to pick at most mm apples. Input The first line of the input contains an integer TT (1≤T≤105)(1≤T≤105) denoting the number of test cases. Each test c…

ruoyi 多模块部署_大数据时代,独立部署的商城系统具有哪些优势?

独立部署是把一个可部署软件包安装到一个指定IT环境上并让其按预定流程提供服务的过程。现如今&#xff0c;越来越多的商家开始搭建网上商城系统&#xff0c;从而为自己积攒多年的客户群体提供更为便捷的购物模式&#xff0c;让购物变得更加智能化。独立部署的商城系统具有哪些…

【SPOJ - DQUERY】D-query(权值树状数组 或 主席树 或 莫队)

题干&#xff1a; Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the subsequence ai, ai1, ..., aj. Inpu…

freerdp 解压安装_Ubuntu下编译安装运作FreeRdp连接Windows

Ubuntu下编译安装运行FreeRdp连接Windows.linux下编译源码进行USB重定向到远程桌面的测试&#xff0c;经过参数的正确配置&#xff0c;可以正常的重定向。具体的操作步骤如下:⑴在虚拟机上安装git,安装命令如&#xff1a;sudo apt-get install git。⑵从GitHub下载FreeRdp源码&…

【HDU - 3328】Flipper (栈模拟)

题干&#xff1a; Problem Description Little Bobby Roberts (son of Big Bob, of Problem G) plays this solitaire memory game called Flipper. He starts with n cards, numbered 1 through n, and lays them out in a row with the cards in order left-to-right. (C…

trunk口不通防火墙_交换机S5700与防火墙USG5500无法对接Eth-trunk LACP-static模式

问题&#xff1a;交换机S5700与防火墙USG5500无法对接Eth-trunk LACP-static模式&#xff0c;两端正常配置后&#xff0c;端口状态显示错误&#xff0c;Eth-trunk端口无法up 。问题描述&#xff1a;交换机侧 GE0/0/5和GE 0/0/6 组成Eth-trunk3 通过LACP-static与防火墙对接&…

【HDU - 1850】Being a Good Boy in Spring Festival (尼姆博弈,nim,异或前缀和)

题干&#xff1a; 一年在外 父母时刻牵挂 春节回家 你能做几天好孩子吗 寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场 悄悄给爸爸买个小礼物 主动地 强烈地 要求洗一次碗 某一天早起 给爸妈用心地做回早餐 如果愿意 你还可以和爸妈说 咱们玩个小游戏吧 ACM课上学的呢…

comsol临时文件夹中有不支持的字符_Editor 常见问题

Editor的数据存在哪里&#xff1f;Editor所处理的数据&#xff0c;就是你自己本地电脑的文件夹、图片、文本文档。除了配置信息、一些必要的临时缓存之外&#xff0c;Editor没有特殊格式的数据。所以&#xff0c;数据都在电脑里&#xff1b;比如说需要备份的话&#xff0c;只要…

【51nod - 1098】 最小方差(基础数学,公式化简,前缀和,积的前缀和)

题干&#xff1a; 若x1,x2,x3……xn的平均数为k。 则方差s^2 1/n * [(x1-k)^2(x2-k)^2…….(xn-k)^2] 。 方差即偏离平方的均值&#xff0c;称为标准差或均方差&#xff0c;方差描述波动程度。 给出M个数&#xff0c;从中找出N个数&#xff0c;使这N个数方差最小。 Input …

【牛客 - 181B】送分题(另类求解a+b,二分)

题干&#xff1a; 对于一套题来说&#xff0c;没有一道送分题&#xff0c;就很不符合常理&#xff0c;但是我又懒得写送分题&#xff0c;所以你可以直接复制以下代码&#xff0c;即可ac本题. #include<cstdio>#include<iostream> using namespace std; int a,…