python - 具有约 2000 万个样本点和千兆字节数据的交互式大图

标签 python performance matplotlib scientific-computing

我在这里遇到了一个问题(我的 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 有很多选项,输出很好,但它是一个巨大的内存 pig ,它从根本上假设你的数据很小。但是还有其他选择。

例如,我使用以下代码生成了一个 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

gnuplot

甚至可以让 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()  

matplotlib

现在,如果您想进行交互,您将不得不将要绘制的数据分箱,并即时放大。我不知道有任何 python 工具可以帮助您临时完成这项工作。

另一方面,绘制大数据是一项非常常见的任务,并且有一些工具可以胜任这项工作。 Paraview是我个人最喜欢的,VisIt是另一个。它们都主要用于 3D 数据,但特别是 Paraview 也可以处理 2d,并且非常具有交互性(甚至具有 Python 脚本界面)。唯一的技巧是将数据写入 Paraview 可以轻松读取的文件格式。

关于python - 具有约 2000 万个样本点和千兆字节数据的交互式大图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5854515/

相关文章:

python - 在 Numpy 中计算累积返回,数组索引问题

performance - 哪些简单的更改对您的 Delphi 程序进行了最大的改进

performance - 数据库规范化设计——单表或多表

python - 如何使用 Spyder 在 Python 中设置绘图的纵横比?

python - 用新的 Dataframe 替换一行

python - 如何通过 executemany() 语句转换 pandas 数据框以进行插入?

c++ - 表访问性能

python - 如何在 Matplotlib 中禁用对数图的小刻度?

python - 改变 plt.imshow() 图像像素的颜色

python - 如何列出 tar 文件的内容而不在 python 中提取它?