如何使用具有大量行的 DataFrame 使线图可读

Posted

技术标签:

【中文标题】如何使用具有大量行的 DataFrame 使线图可读【英文标题】:How to make readable a line plot using a DataFrame with a large number of rows 【发布时间】:2019-08-04 17:48:08 【问题描述】:

我有一个 1,000,000 x 2 的 DataFrame 对象,其中包含我试图从视觉上理解的数据。它基本上模拟了 1,000,000 个事件,其中沿网络传输的数据包根据缓冲区的大小排队或丢弃。因此,两列值是 Packets in Queue 和 Packets Dropped。

我正在尝试使用 Python、Matplotlib 和 Jupyter Notebooks 制作折线图,其中 x 轴上的事件 ID 和 y 轴上特定 ID 点处队列中的数据包数。应该有两行,第一行表示队列中的数据包数,第二行表示丢弃的数据包数。但是,鉴于有超过 1,000,000 次模拟,该图难以理解。这些价值观太挤在一起了。是否可以制作一个包含 1,000,000 个事件实例的可读图表,还是我需要大幅减少事件的数量?

【问题讨论】:

【参考方案1】:

拥有一百万个数据点需要大量的努力并放大才能看到它们的细节。 Plotly 有一些很好的工具可以放大和缩小绘图以及沿 x 轴滑动数据窗口。

如果你对一些平均数没问题,你可以绘制一个移动平均线并接近十万点。您可以将两个子图相互堆叠,以合理详细地查看两列数据。您当然可以对它们进行更多平均,但您会失去查看细节的能力。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def moving_avg(x, N=30):
    return np.convolve(x, np.ones((N,))/N, mode='valid')

plt.figure(figsize = (16,12))

plt.subplot(3,1,1)
x = np.random.random(1000)
plt.plot(x, linewidth = 1, alpha = 0.5, label = 'linewidth = 1')
plt.plot(moving_avg(x, 10), 'C0', label = 'moving average, N = 10')
plt.xlim(0,len(x))
plt.legend(loc=2)

plt.subplot(3,1,2)
x = np.random.random(10000)
plt.plot(x, linewidth = 0.2, alpha = 0.5, label = 'linewidth = 0.2')
plt.plot(moving_avg(x, 100), 'C0', label = 'moving average, N = 100')
plt.xlim(0,len(x))
plt.legend(loc=2)

plt.subplot(3,1,3)
x = np.random.random(100000)
plt.plot(x, linewidth = 0.05, alpha = 0.5, label = 'linewidth = 0.05')
plt.plot(moving_avg(x, 500), 'C0', label = 'moving average, N = 500')
plt.xlim(0,len(x))
plt.legend(loc=2)

plt.tight_layout()

【讨论】:

【参考方案2】:

试试直方图

from matplotlib.pyplot import hist
import pandas as pd
df = pd.DataFrame()
df['x'] = np.random.rand(1000000)
hist(df.index, weights=df.x, bins=1000)
plt.show()

方法 2 线图

df['x'] = np.random.rand(1000000)
df['y'] = np.random.rand(1000000)
w = 1000
v1 = df['x'].rolling(min_periods=1, window=w).sum()[[i*w for i in range(1, int(len(df)/w))]]/w
v2 = df['y'].rolling(min_periods=1, window=w).sum()[[i*w for i in range(1, int(len(df)/w))]]/w
plt.plot(np.arange(len(v1)),v1, c='b')
plt.plot(np.arange(len(v1)),v2, c='r')
plt.show()

我们正在计算 w=1000 点的平均值,即平均 w 值并绘制它们。

每 1000 个间隔扣 1000000 个点时如下所示

【讨论】:

对不起,我应该说它需要是一个有两条线的线图,第一条是队列中的数据包数,第二条是丢弃的数据包数。

以上是关于如何使用具有大量行的 DataFrame 使线图可读的主要内容,如果未能解决你的问题,请参考以下文章

如何找到 DataFrame 行的所有组合?

为啥在具有 1 行的 DataFrame 上的 collect() 使用 2000 个执行器?

如何理解并记忆DataFrame中的Axis参数

如何使用折线图以图形方式显示两个变量之间的相关性(来自同一 DataFrame 的两列)

如何使用角材料在具有可扩展行的表中创建嵌套垫表

带有 HoverTool 的散景线图