我在这里遇到了一个问题(我的RAM):它无法保存我想要绘制的数据.我确实有足够的高清空间.是否有任何解决方案可以避免我的数据集"阴影"?
具体而言,我处理数字信号处理,我必须使用高采样率.我的框架(GNU Radio)以二进制形式保存值(以避免使用太多的磁盘空间).我打开包装.之后我需要策划.我需要可缩放的图和交互式.这是一个问题.
是否有任何优化潜力,或其他软件/编程语言(如R左右)可以处理更大的数据集?实际上我想在我的情节中获得更多数据.但我没有其他软件的经验.GNUplot失败,采用与以下类似的方法.我不知道R(喷射).
import matplotlib.pyplot as plt import matplotlib.cbook as cbook import struct """ plots a cfile cfile - IEEE single-precision (4-byte) floats, IQ pairs, binary txt - index,in-phase,quadrature in plaintext note: directly plotting with numpy results into shadowed functions """ # unpacking the cfile dataset def unpack_set(input_filename, output_filename): index = 0 # index of the samples output_filename = open(output_filename, 'wb') with open(input_filename, "rb") as f: byte = f.read(4) # read 1. column of the vector while byte != "": # stored Bit Values floati = struct.unpack('f', byte) # write value of 1. column to a variable byte = f.read(4) # read 2. column of the vector floatq = struct.unpack('f', byte) # write value of 2. column to a variable byte = f.read(4) # next row of the vector and read 1. column # delimeter format for matplotlib lines = ["%d," % index, format(floati), ",", format(floatq), "\n"] output_filename.writelines(lines) index = index + 1 output_filename.close return output_filename.name # reformats output (precision configuration here) def format(value): return "%.8f" % value # start def main(): # specify path unpacked_file = unpack_set("test01.cfile", "test01.txt") # pass file reference to matplotlib fname = str(unpacked_file) plt.plotfile(fname, cols=(0,1)) # index vs. in-phase # optional # plt.axes([0, 0.5, 0, 100000]) # for 100k samples plt.grid(True) plt.title("Signal-Diagram") plt.xlabel("Sample") plt.ylabel("In-Phase") plt.show(); if __name__ == "__main__": main()
像plt.swap_on_disk()之类的东西可以缓存我的SSD上的东西;)
因此,您的数据并不是那么大,而且您在绘制数据时遇到问题这一事实表明这些工具存在问题.Matplotlib ....不是那么好.它有很多选项,输出很好,但它是一个巨大的记忆力,它从根本上假设你的数据很小.但还有其他选择.
举个例子,我使用以下代码生成了一个20M的数据点文件'bigdata.bin':
#!/usr/bin/env python import numpy import scipy.io.numpyio npts=20000000 filename='bigdata.bin' def main(): data = (numpy.random.uniform(0,1,(npts,3))).astype(numpy.float32) data[:,2] = 0.1*data[:,2]+numpy.exp(-((data[:,1]-0.5)**2.)/(0.25**2)) fd = open(filename,'wb') scipy.io.numpyio.fwrite(fd,data.size,data) fd.close() if __name__ == "__main__": main()
这会生成一个大小约为229MB的文件,这个文件并不是那么大; 但是你已经表示你想要更大的文件,所以你最终会达到内存限制.
让我们首先关注非交互式情节.首先要意识到的是,每个点上都有字形的矢量图将成为一场灾难 - 对于20 M点中的每一点,其中大部分都会重叠,尝试渲染小十字或圆圈或者某些事情正在发生成为一个灾难,产生巨大的文件,并花费大量的时间.这个,我认为默认情况下matplotlib正在下沉.
Gnuplot处理这个问题没有问题:
gnuplot> set term png gnuplot> set output 'foo.png' gnuplot> plot 'bigdata.bin' binary format="%3float32" using 2:3 with dots
甚至可以使Matplotlib表现得谨慎(选择光栅后端,并使用像素标记点):
#!/usr/bin/env python import numpy import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt datatype=[('index',numpy.float32), ('floati',numpy.float32), ('floatq',numpy.float32)] filename='bigdata.bin' def main(): data = numpy.memmap(filename, datatype, 'r') plt.plot(data['floati'],data['floatq'],'r,') plt.grid(True) plt.title("Signal-Diagram") plt.xlabel("Sample") plt.ylabel("In-Phase") plt.savefig('foo2.png') if __name__ == "__main__": main()
现在,如果您想要交互式,那么您将不得不将数据分区以进行绘图,并即时放大.我不知道任何python工具可以帮助你做到这一点.
另一方面,绘制大数据是一项非常常见的任务,并且有一些工具可以胜任这项工作. Paraview是我个人的最爱,VisIt是另一个.它们都主要用于3D数据,但Paraview尤其也是2d,并且非常具有交互性(甚至还有Python脚本界面).唯一的技巧是将数据写入Paraview可以轻松读取的文件格式.
在Ubuntu上对具有1000万点散点图基准的开源交互式绘图软件进行的调查
受到以下描述的用例的启发:https://stats.stackexchange.com/questions/376361/how-to-find-the-sample-points-that-have-statistically-有意义-large-outlier- r我已对其进行基准测试以下非常简单且幼稚的1000万点直线数据的一些实现:
i=0; while [ "$i" -lt 10000000 ]; do echo "$i,$((2 * i)),$((4 * i))"; i=$((i + 1)); done > 10m.csv
前几行10m.csv
如下所示:
0,0,0 1,2,4 2,4,8 3,6,12 4,8,16
基本上,我想:
进行多维数据的XY散点图,希望将Z作为点颜色
互动地选择一些有趣的看点
查看所选点的所有尺寸以尝试了解为什么它们在XY散点中是异常值
为了获得更多乐趣,我还准备了更大的10亿点数据集,以防任何程序可以处理1000万点!CSV文件变得有点奇怪,我转到HDF5:
import h5py import numpy size = 1000000000 with h5py.File('1b.hdf5', 'w') as f: x = numpy.arange(size + 1) x[size] = size / 2 f.create_dataset('x', data=x, dtype='int64') y = numpy.arange(size + 1) * 2 y[size] = 3 * size / 2 f.create_dataset('y', data=y, dtype='int64') z = numpy.arange(size + 1) * 4 z[size] = -1 f.create_dataset('z', data=z, dtype='int64')
这将产生一个〜23GiB文件,该文件包含一条直线,就像10m.csv
在图的中心顶部一样,还有一个离群值。
除非另有说明,否则测试是在Ubuntu 18.10中进行的,除非在本节中另有说明,否则将在具有Intel Core i7-7820HQ CPU(4核/ 8线程),2个Samsung M471A2K43BB1-CRC RAM(2个16GiB),NVIDIA Quadro M1200的ThinkPad P51笔记本电脑中进行4GB GDDR5 GPU。
结果汇总
考虑到我非常特定的测试用例,并且我是许多经过审查的软件的第一次用户,这就是我观察到的:
它可以处理1000万点吗?
Vaex Yes, tested up to 1 Billion! VisIt Yes, but not 100m Paraview Barely Mayavi Yes gnuplot Barely on non-interactive mode. matplotlib No Bokeh No, up to 1m PyViz ? seaborn ?
它有很多功能吗?
Vaex Yes. VisIt Yes, 2D and 3D, focus on interactive. Paraview Same as above, a bit less 2D features maybe. Mayavi 3D only, good interactive and scripting support, but more limited features. gnuplot Lots of features, but limited in interactive mode. matplotlib Same as above. Bokeh Yes, easy to script. PyViz ? seaborn ?
GUI是否感觉良好(不考虑良好的性能):
Vaex Yes, Jupyter widget VisIt No Paraview Very Mayavi OK gnuplot OK matplotlib OK Bokeh Very, Jupyter widget PyViz ? seaborn ?
Vaex 2.0.2
https://github.com/vaexio/vaex
安装并获得一个hello world的工作,如以下所示:如何在Vaex中进行交互式2D散点图缩放/点选择?
我测试了vaex最高10亿分,而且效果很好,太棒了!
这是“ Python脚本优先”的代码,它具有很高的可重复性,使我可以轻松地与其他Python东西交互。
Jupyter设置有几个活动的部分,但是一旦我使它与virtualenv一起运行,那就太神奇了。
要加载在Jupyter中运行的CSV:
import vaex df = vaex.from_csv('10m.csv', names=['x', 'y', 'z'],) df.plot_widget(df.x, df.y, backend='bqplot')
我们可以立即看到:
现在,我们可以用鼠标缩放,平移和选择点,并且更新非常快,所有这些操作都在10秒内完成。在这里,我进行了放大以查看一些单独的点,并选择了其中一些(图像上较淡的矩形):
用鼠标进行选择后,其效果与使用该df.select()
方法完全相同。因此,我们可以通过在Jupyter中运行来提取所选点:
df.to_pandas_df(selection=True)
输出格式为:
x y z index 0 4525460 9050920 18101840 4525460 1 4525461 9050922 18101844 4525461 2 4525462 9050924 18101848 4525462 3 4525463 9050926 18101852 4525463 4 4525464 9050928 18101856 4525464 5 4525465 9050930 18101860 4525465 6 4525466 9050932 18101864 4525466
由于10M点效果很好,所以我决定尝试1B点!
import vaex df = vaex.open('1b.hdf5') df.plot_widget(df.x, df.y, backend='bqplot')
要观察离群值,该离群值在原始图上是不可见的,我们可以遵循如何在vaex交互式Jupyter bqplot plot_widget中更改点样式以使单个点变大和可见?并使用:
df.plot_widget(df.x, df.y, f='log', shape=128, backend='bqplot')
产生:
然后选择点:
我们获得异常值的完整数据:
x y z 0 500000000 1500000000 -1
这是创作者的演示,具有更多有趣的数据集和更多功能:https : //www.youtube.com/watch?v=2Tt0i823-ec&t=770
在Ubuntu 19.04中测试。
VisIt 2.13.3
网站:https://wci.llnl.gov/simulation/computer-codes/visit
许可证:BSD
由劳伦斯·利弗莫尔国家实验室(Lawrence Livermore National Laboratory)开发,该实验室是国家核安全局(National Nuclear Security Administration)的实验室,因此,如果我能使它正常工作,那么您可以想象1000万点将毫无用处。
安装:没有Debian软件包,只需从网站下载Linux二进制文件即可。无需安装即可运行。另请参阅:https : //askubuntu.com/questions/966901/installing-visit
基于VTK,这是许多高性能绘图软件使用的后端库。用C写。
经过3个小时的用户界面玩后,我确实可以使用它了,并且确实可以解决我的用例,详情如下:https : //stats.stackexchange.com/questions/376361/how-to-find-the-sample-具有统计意义的大离群值r
这是此帖子的测试数据的外观:
和一些选择的变焦:
这是选择窗口:
在性能方面,VisIt很好:每个图形操作要么只花费很少的时间,要么立即执行,我认为它可以轻松处理更多数据。当我不得不等待时,它会显示“正在处理”消息以及剩余的工作量百分比,并且GUI并未冻结。
由于10m点工作得很好,所以我也尝试了100m点(一个2.7G CSV文件),但不幸的是它崩溃了/进入了一个奇怪的状态,我看着它进入htop
了视线,因为4个VisIt线程占用了我所有的16GiB RAM并可能是由于死了到失败的malloc。
最初的入门有点痛苦:
如果您不是核弹工程师,那么许多默认设置都会让人感到残酷吗?例如:
默认点大小1px(在显示器上被灰尘弄脏)
轴的比例从0.0到1.0:如何在“访问”绘图程序中显示实际的轴数值,而不是从0.0到1.0的分数?
多窗口设置,选择数据点时讨厌的多弹出窗口
显示您的用户名和打印日期(通过“控件”>“注释”>“用户信息”删除)
自动定位默认设置很糟糕:图例与坐标轴冲突,找不到标题自动化,因此不得不添加标签并手动重新放置所有内容
只有很多功能,因此很难找到想要的功能
该手册非常有帮助,但是它是一个386页PDF庞然大物,日期不详,日期为“ October 2005 Version 1.5”。我不知道他们是否以此来发展Trinity!这是我最初回答此问题后创建的一个很好的Sphinx HTML
没有Ubuntu软件包。但是预编译的二进制文件确实可以工作。
我将这些问题归因于:
它已经存在了很长时间,并使用了一些过时的GUI创意
您不能只单击绘图元素来更改它们(例如,轴,标题等),并且有很多功能,因此很难找到想要的功能
我也很喜欢LLLL基础设施如何泄漏到该存储库中。请参阅例如docs / OfficeHours.txt和该目录中的其他文件!我为“星期一早上的家伙”布拉德(Brad)感到抱歉!哦,答录机的密码是“ Kill Ed”,请不要忘记这一点。
视点5.4.1
网站:https://www.paraview.org/
许可证:BSD
安装:
sudo apt-get install paraview
由桑迪亚国家实验室(Sandia National Laboratories)开发,该实验室是NNSA的另一个实验室,因此我们再次希望它可以轻松处理数据。也是基于VTK并用C ++编写的,这进一步受到了欢迎。
但是我很失望:由于某种原因,1000万点使GUI非常缓慢且无响应。
我对广告中的“我现在正在工作,稍等片刻”的广告打得很好,但GUI冻结了,这会发生吗?不能接受的。
htop显示Paraview正在使用4个线程,但是CPU和内存均未达到极限。
在GUI方面,Paraview非常美观和现代,在不卡口的情况下比VisIt更好。这是一个较低的点数供参考:
这是带有手动点选择的电子表格视图:
另一个缺点是与VisIt相比,Paraview感觉缺乏功能,例如:
我找不到如何根据第三列设置散点图的颜色的方法:如何像gnuplot调色板一样通过Paraview中第三列的值为散点图设置颜色?
无法调整标记大小!!!!https://gitlab.kitware.com/paraview/paraview/issues/14169
Mayavi 4.6.2
网站:https://github.com/enthought/mayavi
开发者:有思想的
安装:
sudo apt-get install libvtk6-dev python3 -m pip install -u mayavi PyQt5
VTK Python之一。
Mayavi似乎非常专注于3D,我找不到在其中进行2D绘制的方法,因此不幸的是,它并没有削减它的使用范围。
但是,为了检查性能,我改编了以下示例:https : //docs.enthought.com/mayavi/mayavi/auto/example_scatter_plot.html,获得了1000万分,并且运行良好,没有滞后:
import numpy as np from tvtk.api import tvtk from mayavi.scripts import mayavi2 n = 10000000 pd = tvtk.PolyData() pd.points = np.linspace((1,1,1),(n,n,n),n) pd.verts = np.arange(n).reshape((-1, 1)) pd.point_data.scalars = np.arange(n) @mayavi2.standalone def main(): from mayavi.sources.vtk_data_source import VTKDataSource from mayavi.modules.outline import Outline from mayavi.modules.surface import Surface mayavi.new_scene() d = VTKDataSource() d.data = pd mayavi.add_source(d) mayavi.add_module(Outline()) s = Surface() mayavi.add_module(s) s.actor.property.trait_set(representation='p', point_size=1) main()
输出:
但是,我无法放大到足以看到单个点的地方,近3D平面太远了。也许有办法吗?
关于Mayavi的一件很酷的事情是,开发人员付出了很多努力,使您可以很好地从Python脚本启动和设置GUI,就像Matplotlib和gnuplot一样。似乎在Paraview中也可以做到这一点,但是文档至少不那么好。
通常,感觉不像VisIt / Paraview那样功能齐全。例如,我无法直接从GUI 加载CSV:如何从Mayavi GUI加载CSV文件?
Gnuplot 5.2.2
网址:http://www.gnuplot.info/
当我需要快速又肮脏时,gnuplot真的很方便,这始终是我尝试的第一件事。
安装:
sudo apt-get install gnuplot
对于非交互使用,它可以合理地处理10m个点:
#!/usr/bin/env gnuplot set terminal png size 1024,1024 set output "gnuplot.png" set key off set datafile separator "," plot "10m1.csv" using 1:2:3:3 with labels point
在7秒内完成:
但是如果我尝试与
#!/usr/bin/env gnuplot set terminal wxt size 1024,1024 set key off set datafile separator "," plot "10m.csv" using 1:2:3 palette
和:
gnuplot -persist main.gnuplot
那么初始渲染和缩放就太迟钝了。我什至看不到矩形选择线!
还要注意,对于我的用例,我需要使用超文本标签,如下所示:
plot "10m.csv" using 1:2:3 with labels hypertext
但是标签功能(包括非交互式渲染)存在性能错误。但是我报告了它,伊桑(Ethan)在一天之内解决了它:https : //groups.google.com/forum/#!topic/comp.graphics.apps.gnuplot/qpL8aJIi9ZE
但是,我必须说,有一种合理的方法可以选择异常值:只需将带有行ID的标签添加到所有点!如果附近有很多点,您将无法阅读标签。但是对于您关心的离群值,您可能会!例如,如果我在原始数据中添加一个异常值:
cp 10m.csv 10m1.csv printf '2500000,10000000,40000000\n' >> 10m1.csv
并将plot命令修改为:
#!/usr/bin/env gnuplot set terminal png size 1024,1024 set output "gnuplot.png" set key off set datafile separator "," plot "10.csv" using 1:2:3:3 palette with labels
这显着减慢了绘图速度(在上述修复后40分钟),但产生了合理的输出:
因此,通过一些数据过滤,我们最终会到达那里。
Matplotlib 1.5.1,numpy 1.11.1,Python 3.6.7
网站:https://matplotlib.org/
当我的gnuplot脚本开始变得太疯狂时,我通常会尝试使用Matplotlib。
numpy.loadtxt
一个人花了大约10秒钟,所以我知道这不会进展顺利:
#!/usr/bin/env python3 import numpy import matplotlib.pyplot as plt x, y, z = numpy.loadtxt('10m.csv', delimiter=',', unpack=True) plt.figure(figsize=(8, 8), dpi=128) plt.scatter(x, y, c=z) # Non-interactive. #plt.savefig('matplotlib.png') # Interactive. plt.show()
首先,非交互式尝试提供了良好的输出,但耗时3分55秒...
然后,交互式互动程序在初始渲染和缩放上花费了很长时间。无法使用:
请注意,在此屏幕截图中,应立即缩放并消失的缩放选择在等待计算缩放时在屏幕上停留了很长时间!
plt.figure(figsize=(8, 8), dpi=128)
由于某种原因,我不得不注释掉交互式版本才能工作,否则它会被炸毁:
RuntimeError: In set_size: Could not set the fontsize
散景1.3.1
https://github.com/bokeh/bokeh
Ubuntu 19.04安装:
python3 -m pip install bokeh
然后启动Jupyter:
jupyter notebook
现在,如果我绘制1m点,则一切工作正常,界面很棒且快速,包括缩放和悬停信息:
from bokeh.io import output_notebook, show from bokeh.models import HoverTool from bokeh.transform import linear_cmap from bokeh.plotting import figure from bokeh.models import ColumnDataSource import numpy as np N = 1000000 source = ColumnDataSource(data=dict( x=np.random.random(size=N) * N, y=np.random.random(size=N) * N, z=np.random.random(size=N) )) hover = HoverTool(tooltips=[("z", "@z")]) p = figure() p.add_tools(hover) p.circle( 'x', 'y', source=source, color=linear_cmap('z', 'Viridis256', 0, 1.0), size=5 ) show(p)
初始视图:
缩放后:
如果我阻塞了10m,htop
表明铬有8个线程以不间断的IO状态占用了我的所有内存。
这询问有关参考点的问题:如何参考选定的bokeh背景数据点
毕威士
https://pyviz.org/
TODO评估。
集成Bokeh + datashader +其他工具。
视频演示1B数据点:https : //www.youtube.com/watch? v = k27MJJLJNT4“ PyViz:仪表板,用于在30行Python中可视化10亿个数据点”,“ Anaconda,Inc.” 发表于2018-04-17。
海生的
https://seaborn.pydata.org/
TODO评估。
已经有关于如何使用seaborn可视化至少5000万行的质量检查。
您当然可以优化文件的读取:您可以直接将其读入NumPy数组,以便利用NumPy的原始速度.你有几个选择.如果RAM是个问题,你可以使用memmap,它将大部分文件保存在磁盘上(而不是RAM中):
# Each data point is a sequence of three 32-bit floats: data = np.memmap(filename, mode='r', dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])
如果RAM不是问题,您可以使用fromfile将整个数组放在RAM中:
data = np.fromfile(filename, dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])
然后可以使用Matplotlib的常用plot(*data)
功能完成绘图,可能通过另一种解决方案中提出的"放大"方法.
最近的一个项目具有很强的大数据集潜力:Bokeh,正是考虑到这一点而创建的.
实际上,只有与绘图比例相关的数据才会被发送到显示后端.这种方法比Matplotlib方法快得多.
我会建议一些有点复杂的东西,但这应该有效:在不同的分辨率,不同的范围内构建你的图形.
例如,想想谷歌地球.如果你以最大水平解锁以覆盖整个行星,则分辨率最低.缩放时,图片会更改为更详细的图片,但只会在您放大的区域上.
所以基本上对于你的情节(是2D?3D?我会假设它是2D),我建议你构建一个覆盖整个[0,n]范围的大图,低分辨率,2个较小的图覆盖[0,n/2]和[n/2 + 1,n]的分辨率是大的两倍,4个较小的图覆盖[0,n/4] ... [3*n/4 + 1,n]两次上面2的分辨率,依此类推.
不确定我的解释是否清楚.此外,我不知道这种多分辨率图是否由任何现有的绘图程序处理.