基于Processing的数据可视化
虽然数据可视化领域有很多成熟、界面友好、功能强大的软件产品(例如Tableau、VIDI、NodeXL等),但是借助Processing我们可以基于Java语言框架进行丰富多元的可视化编程,熟悉了Processing也可以说是上一学期Topics课程的最大收获,以另一种方式将数据重新组织、统计并以可视化界面展现出来。今天再看其他资料时碰巧看到XX对Processing的支持,颇感亲切,所以决定把上学期Topics的作业过程记录下来。
可视化内容是从Databank下载的217个国家、6个地区的7项统计数据。要求从通过数据可视化看出每个指标的变化趋势、所选不同国家之间的对比情况、不同时间段数据变化、不同地区所包含国家的统计数据对比等。
– Electricity production (kWh)
– Electricity production from renewable sources (kWh)
– Electric power consumption (kWh)
– Electric power consumption (kWh per capita)
– CO2 emissions (metric tons per capita)
– CO2 emissions (kt)
– Population, total
数据文件如下:

最终可视化结果如下:




源码如下:
import processing.core.*;
import processing.data.*;
import processing.event.*;
import processing.opengl.*; import controlP5.*;
import java.lang.Math; import java.util.HashMap;
import java.util.ArrayList;
import java.io.File;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException; public class TCS1 extends PApplet { ControlP5 cp5; FloatTable data, dataRegion;
float dataMin, dataMax;
float volumnMax; float plotX1, plotY1;
float plotX2, plotY2;
float labelX, labelY; int yearMin, yearMax;
int[] years;
int yearInterval = 3; int showRow = 6;
int showRegionRow = 0; int yearStartCol = 8; //Integrator[] interpolators; PFont plotFont;
DropdownList dropCountry, dropCate, dropRegion; boolean isNormalOn = true;
boolean isGroupOn = false;
boolean isCompareOn = false; int groupMode = 1;
static final int GROUP_MODE_REGIONS = 1;
static final int GROUP_MODE_DECADES = 2; IntList listCompare = new IntList();
int[][] compareColors = new int[300][3];
int cateCompare = 0; int[] decadeYearIndex = new int[4];
String[] decadeYearStr = new String[4]; public void setup() {
size(1200, 750); cp5 = new ControlP5(this);
data = new FloatTable("data.tsv");
dataRegion = new FloatTable("region.tsv"); years = PApplet.parseInt(data.getColumnNames()); yearMin = years[yearStartCol];
yearMax = years[years.length - 1]; //init decade year
for (int i=7; i>3; i--) {
decadeYearStr[7-i] = data.getColumnNames()[i];
decadeYearIndex[7-i] = 7-i;
} interpolators = new Integrator[data.getColumnCount()];
for(int col=yearStartCol; col=weishu; i--) {
maxStr += "0";
eachStr += "0";
}
eachStr += "0" + firstNum;
maxStr += firstNum + "";
}
else {
for (int i=-1; i>=weishu+1; i--) {
maxStr += "0";
eachStr += "0";
}
eachStr += "0" + firstNum;
maxStr += firstNum + "";
}
}
else if (weishu == 0) {
if (firstNum != 10) {
maxStr = "0."+firstNum;
eachStr = "0.0" + firstNum;
}
else {
maxStr = firstNum / 10 + "";
eachStr = "0." + firstNum / 10;
}
}
else if (weishu == 1) {
if (firstNum != 10) {
maxStr = firstNum + "";
eachStr = "0." + firstNum;
}
else {
maxStr = firstNum + "";
eachStr = firstNum / 10 + "";
}
}
else {
maxStr += firstNum + "";
eachStr += firstNum + "";
for (int i=1; i= 10) {
if (weishu == 0) {
volumnNumbers[i] = currentFirstNum / 100 + "";
}
else {
volumnNumbers[i] = currentFirstNum / pow(10, 2-weishu) + "";
}
}
else if (PApplet.parseFloat(currentFirstNum) / 10 >= 1) {
volumnNumbers[i] += "0.";
for (int j=-1; j>weishu-1;j--) {
volumnNumbers[i] += "0";
}
volumnNumbers[i] += currentFirstNum;
}
else {
volumnNumbers[i] += "0.";
for (int j=-1; j>weishu-2;j--) {
volumnNumbers[i] += "0";
}
volumnNumbers[i] += currentFirstNum;
}
}
else if (weishu == 1) {
if (PApplet.parseFloat(currentFirstNum) / 10 >= 1) { volumnNumbers[i] = (currentFirstNum / 10) + "." + (currentFirstNum - ((currentFirstNum / 10) * 10));
}
else {
volumnNumbers[i] = "0."+currentFirstNum;
}
}
else {
volumnNumbers[i] = currentFirstNum + "";
for (int j=0; j 0) {
if (v > 100) {
return String.format("%.0f", v);
}
else if (v > 10) {
return String.format("%.2f", v);
}
else if (v > 1) {
return String.format("%.3f", v);
}
else {
return String.format("%.4f", v);
}
}
return "";
} public void drawDataPoints(int row) {
for (int col=yearStartCol; col3; col--) {
if (data.isValid(row, col)) {
float value = data.getFloat(row, col);
System.out.println(value);
float x = map(decadeYearIndex[7-col], -0.7f, 3.7f, plotX1, plotX2);
float y = map(value, 0, volumnMax, plotY2, plotY1); rect(x-(recWidth / 2), y, recWidth, plotY2 - y); text(value, x, y - 20);
}
}
} public void drawDataLine(int row) {
beginShape();
//stroke(23, 23, 23);
for (int col=yearStartCol; col= data.length)) {
throw new RuntimeException("There is no row " + rowIndex);
}
if ((col < 0) || (col >= data[rowIndex].length)) {
throw new RuntimeException("Row " + rowIndex + " does not have a column " + col);
}
// end training wheels return data[rowIndex][col];
} public boolean isValid(int row, int col) {
//System.out.println("data[6].length" + data[6].length);
if (row < 0) return false;
if (row >= rowCount) return false;
//if (col >= columnCount) return false;
if (col >= data[row].length) return false;
if (col < 0) return false;
if(data[row][col] == 0) return false;
return !Float.isNaN(data[row][col]);
} public float getColumnMin(int col) {
float m = Float.MAX_VALUE;
for (int row = 0; row < rowCount; row++) {
if (isValid(row, col)) {
if (data[row][col] < m) {
m = data[row][col];
}
}
}
return m;
} public float getColumnMax(int col) {
float m = -Float.MAX_VALUE;
for (int row = 0; row < rowCount; row++) {
if (isValid(row, col)) {
if (data[row][col] > m) {
m = data[row][col];
}
}
}
return m;
} public float getRowMin(int row) {
float m = Float.MAX_VALUE;
for (int col = 0; col < columnCount; col++) {
if (isValid(row, col)) {
if (data[row][col] < m) {
m = data[row][col];
}
}
}
return m;
} public float getRowMax(int row) {
float m = -Float.MAX_VALUE;
for (int col = 0; col < columnCount; col++) {
if (isValid(row, col)) {
if (data[row][col] > m) {
m = data[row][col];
}
}
}
return m;
} public float getTableMin() {
float m = Float.MAX_VALUE;
for (int row = 0; row < rowCount; row++) {
for (int col = 0; col < columnCount; col++) {
if (isValid(row, col)) {
if (data[row][col] < m) {
m = data[row][col];
}
}
}
}
return m;
} public float getTableMax() {
float m = -Float.MAX_VALUE;
for (int row = 0; row < rowCount; row++) {
for (int col = 0; col < columnCount; col++) {
if (isValid(row, col)) {
if (data[row][col] > m) {
m = data[row][col];
}
}
}
}
return m;
} public boolean hasData(int row, int startCol) {
boolean hasData = false;
for (int col = startCol; col < columnCount; col++) {
//System.out.println("row="+row+" col="+col+" isValid="+isValid(row, col));
if (isValid(row, col)) {
hasData = true;
break;
}
}
return hasData;
} public float getRowMin(int row, int startCol) {
float m = Float.MAX_VALUE;
for (int col = startCol; col < columnCount; col++) { //System.out.println("row="+row+" col="+col+" isValid="+isValid(row, col));
if (isValid(row, col)) {
if (data[row][col] < m) {
m = data[row][col];
}
}
}
return m;
} public float getRowMax(int row, int startCol) {
float m = -Float.MAX_VALUE;
for (int col = startCol; col < columnCount; col++) {
//System.out.println("row="+row+" col="+col+" isValid="+isValid(row, col));
if (isValid(row, col)) {
if (data[row][col] > m) {
m = data[row][col];
}
}
}
return m;
} public float getRowMin(int row, int startCol, int endCol) {
float m = Float.MAX_VALUE;
for (int col = startCol; col < endCol + 1; col++) { //System.out.println("row="+row+" col="+col+" isValid="+isValid(row, col));
if (isValid(row, col)) {
if (data[row][col] < m) {
m = data[row][col];
}
}
}
return m;
} public float getRowMax(int row, int startCol, int endCol) {
float m = -Float.MAX_VALUE;
for (int col = startCol; col < endCol + 1; col++) {
//System.out.println("row="+row+" col="+col+" isValid="+isValid(row, col));
if (isValid(row, col)) {
if (data[row][col] > m) {
m = data[row][col];
}
}
}
return m;
}
}
class Integrator { final float DAMPING = 0.5f;
final float ATTRACTION = 0.2f; float value;
float vel;
float accel;
float force;
float mass = 1; float damping = DAMPING;
float attraction = ATTRACTION;
boolean targeting;
float target; Integrator() { } Integrator(float value) {
this.value = value;
} Integrator(float value, float damping, float attraction) {
this.value = value;
this.damping = damping;
this.attraction = attraction;
} public void set(float v) {
value = v;
} public void update() {
if (targeting) {
force += attraction * (target - value);
} accel = force / mass;
vel = (vel + accel) * damping;
value += vel; force = 0;
} public void target(float t) {
targeting = true;
target = t;
} public void noTarget() {
targeting = false;
}
}
static public void main(String[] passedArgs) {
String[] appletArgs = new String[] { "TCS1" };
if (passedArgs != null) {
PApplet.main(concat(appletArgs, passedArgs));
} else {
PApplet.main(appletArgs);
}
}
}
基于Processing的数据可视化的更多相关文章
- 基于matplotlib的数据可视化 - 笔记
1 基本绘图 在plot()函数中只有x,y两个量时. import numpy as np import matplotlib.pyplot as plt # 生成曲线上各个点的x,y坐标,然后用一 ...
- ARDUNIO IMU processing姿态数据可视化
https://www.arduino.cn/thread-42852-1-1.html 关键数据打包 float roll, pitch, heading; Serial.print("O ...
- 基于matplotlib的数据可视化 - 饼状图pie
绘制饼状图的基本语法 创建数组 x 的饼图,每个楔形的面积由 x / sum(x) 决定: 若 sum(x) < 1,则 x 数组不会被标准化,x 值即为楔形区域面积占比.注意,该种情况会出现 ...
- 基于matplotlib的数据可视化 - 热图imshow
热图: Display an image on the axes. 可以用来比较两个矩阵的相似程度 mp.imshow(z, cmap=颜色映射,origin=垂直轴向) imshow( X, cma ...
- 基于matplotlib的数据可视化 - 等高线 contour 与 contourf
contour 与contourf 是绘制等高线的利器. contour - 绘制等高线 contourf - 填充等高线 两个的返回值值是一样的(return values are the sam ...
- 基于matplotlib的数据可视化 -
matplotlib.pyplot(as mp or as plt)提供基于python语言的绘图函数 引用方式: import matplotlib.pyplot as mp / as plt 本章 ...
- 基于matplotlib的数据可视化 - 三维曲面图gca
1 语法 ax = plt.gca(projection='3d')ax.plot_surface(x,y,z,rstride=行步距,cstride=列步距,cmap=颜色映射) gca(**kwa ...
- 基于matplotlib的数据可视化 - 柱状图bar
柱状图bar 柱状图常用表现形式为: plt.bar(水平坐标数组,高度数组,宽度比例,ec=勾边色,c=填充色,label=图例标签) 注:当高度值为负数时,柱形向下 1 语法 bar(*args, ...
- 基于matplotlib的数据可视化(图形填充fill fill_between) - 笔记(二)
区域填充函数有 fill(*args, **kwargs) 和fill_between() 1 绘制填充多边形fill() 1.1 语法结构 fill(*args, **kwargs) args - ...
随机推荐
- NFC简介
NFC简介 NFC是Near Field Communication缩写,即近距离无线通讯技术.由飞利浦和索尼公司共同开发的NFC是一种非接触式识别和互联技术,可以在移动设备.消费类电子产品.PC 和 ...
- json解析异常 - net.sf.json.JSONException: java.lang.reflect.InvocationTargetException
注:在项目中, 我使用原生的ajax请求数据的时候, JSONObject没能帮我解析, 当却不给我报错, 我是在junit单元测试中测试的时候, 发现的.发现好多时候, 特别是通过ajax请求, 不 ...
- http和HTTPS的区别及SSL介绍
简单来说: 在URL前加https://前缀表明是用SSL加密的. 你的电脑与服务器之间收发的信息传输将更加安全. Web服务器启用SSL需要获得一个服务器证书并将该证书与要使用SSL的服务器绑定. ...
- 网络基础---OSI 模型与TCP/IP
一.网络的演进: 1.简单的联接:1960's ------------ 1970's Host Network 六十至七十年代,网络的概念主要是主机架构的低速串行联接,提供应用程序执行.远程打 ...
- django添加静态文件
最近做了一个todolist webapp,需要稍微添加css时候又忘记django的添加方法了,查看了以前的项目才想起来,所以记录一下. 1.settings.py 将以下代码放到最下面 STATI ...
- linux用户管理,linux用户口令管理,linux用户组管理,linux用户权限管理详解
linux用户管理 http://www.qq210.com/shoutu/android 用户账号的添加(新加用户需添加用户口令) :增加用户账号就是在/etc/passwd文件中为新用户增加一条记 ...
- 最常见的HTTP错误
1. HTTP 500错误(内部服务器错误)对对HTTP 500错误的定义已经充分证明了这是一个最常见的HTTP错误. 一般来说,HTTP 500 错误就是web服务器发生内部错误时返回的信息. 例如 ...
- adb找不到设备
提示信息如下所示: adb server is out of date.killing... adb server didn't ACK *failed to start daemon * error ...
- ASP.NET MVC轻教程 Step By Step 5——初识表单
上一节我们将留言列表显示在Index视图里了,现在该添加一个留言的表单,好让用户自己添加留言. 首先在HomeController中添加一个名为“Write”的动作方法. public ActionR ...
- 通过CTAPI和Citect SCADA软件进行数据通讯
官方文档 Citect SCADA 7.20 Technical Reference 参考文献 基于Citect远程控制的变流量堆料控制系统 [王玉增,顾英妮,王维 济南大学,机械工程学院 ,Cite ...