如何动态更新循环中的绘图?

时间:2015-07-13 10:19:08

标签: python pandas matplotlib

我有以下代码片段,我希望以一种方式扩展,即每个循环的数据在同一画布上绘制,而不是每个循环绘制到不同的循环。

for level in range(len(result)):
  sizes = result[level].values()
  distribution=pd.DataFrame(Counter(sizes).items(), columns=['community size','number of communities'])
  distribution.plot(kind='scatter', x='community size', y='number of communities')

在最佳情况下,我还希望根据原始数据对散点图中的点进行颜色编码(属于来自同一颜色的一个循环数据的点)。

我或多或少都对matplotlib和pandas都是新手,所以非常感谢andy帮助。

1 个答案:

答案 0 :(得分:1)

您可以将整个数据集构建为一个,而不是多次调用plot DataFrame然后您只需要调用plot一次。

开始
result = [{0: 21, 1: 7, 2: 67, 3: 12, 4: 15, 5: 7, 6: 54, 7: 49, 8: 50, 9: 31,
           10: 6, 11: 2, 12: 8, 13: 2, 14: 2, 15: 1, 16: 35, 17: 2, 18: 1, 19:
           4, 20: 2, 21: 4, 22: 3, 23: 1, 24: 1, 25: 1, 26: 1, 27: 1, 28: 1, 
           29: 1}, 
          {0: 2, 1: 5, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3, 7: 2, 8: 1, 9: 1, 10: 1,
           11: 1, 12: 1, 13: 1, 14: 1, 15: 1, 16: 1, 17: 1}]

您可以使用列levelsize构建一个DataFrame:

df = pd.DataFrame([(level,val) for level, dct in enumerate(result) 
                   for val in dct.values()],
                  columns=['level', 'size'])

看起来像这样:

    level  size
0       0    21
1       0     7
2       0    67
...
45      1     1
46      1     1
47      1     1

现在我们可以按级别进行分组,并计算每个组中每个size的项目数:

size_count = df.groupby(['level'])['size'].apply(lambda x: x.value_counts())
# level    
# 0      1      9
#        2      5
#        7      2
# ...
# 1      1     11
#        2      4
#        3      2
#        5      1
# dtype: int64

上面的groupby/apply会返回pd.Series。为了使其成为DataFrame,我们可以通过调用reset_index()将索引级别值设置为列,然后将列名称分配给列:

size_count = size_count.reset_index()
size_count.columns = ['level', 'community size', 'number of communities']

现在可以使用

生成所需的绘图
size_count.plot(kind='scatter', x='community size', y='number of communities', 
                s=100, c='level')

s=100控制点的大小,c='level'告诉plot根据level列中的值为点着色。

import pandas as pd
import matplotlib.pyplot as plt

result = [{0: 21, 1: 7, 2: 67, 3: 12, 4: 15, 5: 7, 6: 54, 7: 49, 8: 50, 9: 31,
           10: 6, 11: 2, 12: 8, 13: 2, 14: 2, 15: 1, 16: 35, 17: 2, 18: 1, 19:
           4, 20: 2, 21: 4, 22: 3, 23: 1, 24: 1, 25: 1, 26: 1, 27: 1, 28: 1, 
           29: 1}, 
          {0: 2, 1: 5, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3, 7: 2, 8: 1, 9: 1, 10: 1,
           11: 1, 12: 1, 13: 1, 14: 1, 15: 1, 16: 1, 17: 1}]

df = pd.DataFrame([(level,val) for level, dct in enumerate(result) 
                   for val in dct.values()],
                  columns=['level', 'size'])
size_count = df.groupby(['level'])['size'].apply(lambda x: x.value_counts())
size_count = size_count.reset_index()
size_count.columns = ['level', 'community size', 'number of communities']
cmap = plt.get_cmap('jet')
size_count.plot(kind='scatter', x='community size', y='number of communities', 
                s=100, c='level', cmap=cmap)
plt.show()

enter image description here

如果存在数十个级别,则使用颜色栏可能是合适的。

另一方面,如果只有几个级别,则使用图例 更有意义。在这种情况下,为每个人调用plot一次会更方便 级别值,因为matplotlib代码使得图例设置为make 每个情节一个传奇条目:

import pandas as pd
import matplotlib.pyplot as plt

result = [{0: 21, 1: 7, 2: 67, 3: 12, 4: 15, 5: 7, 6: 54, 7: 49, 8: 50, 9: 31,
           10: 6, 11: 2, 12: 8, 13: 2, 14: 2, 15: 1, 16: 35, 17: 2, 18: 1, 19:
           4, 20: 2, 21: 4, 22: 3, 23: 1, 24: 1, 25: 1, 26: 1, 27: 1, 28: 1, 
           29: 1}, 
          {0: 2, 1: 5, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3, 7: 2, 8: 1, 9: 1, 10: 1,
           11: 1, 12: 1, 13: 1, 14: 1, 15: 1, 16: 1, 17: 1}]

df = pd.DataFrame([(level,val) for level, dct in enumerate(result) 
                   for val in dct.values()],
                  columns=['level', 'size'])
groups = df.groupby(['level'])
fig, ax = plt.subplots()
for level, grp in groups:
    size_count = grp['size'].value_counts()
    ax.plot(size_count.index, size_count, markersize=12, marker='o', 
            linestyle='', label='level {}'.format(level))
ax.legend(loc='best', numpoints=1)
ax.set_xlabel('community size')
ax.set_ylabel('number of communities')
ax.grid(True)
plt.show()

enter image description here