python - How to dynamically update a plot in a loop? -
i have following snippet extend in way data each loop gets plotted on same canvas instead of each loop different one.
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') in optimal case additionally have dots in scatterplot color-coded according original data (dots belonging data 1 loop colored in same color).
i more or less new both matplotlib , pandas, andy highly appreciated.
instead of calling plot many times, build entire data set 1 dataframe , need call plot once.
starting
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}] you build dataframe columns level , size:
df = pd.dataframe([(level,val) level, dct in enumerate(result) val in dct.values()], columns=['level', 'size']) which looks this:
level size 0 0 21 1 0 7 2 0 67 ... 45 1 1 46 1 1 47 1 1 now can group level, , count how many items of each size there in each group:
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 the groupby/apply above returns pd.series. make dataframe, can make index level values columns calling reset_index(), , assign column names columns:
size_count = size_count.reset_index() size_count.columns = ['level', 'community size', 'number of communities'] now desired plot can generated with
size_count.plot(kind='scatter', x='community size', y='number of communities', s=100, c='level') s=100 controls size of dots, c='level' tells plot color dots according value in level column.
import pandas pd import matplotlib.pyplot 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) level, dct in enumerate(result) 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() 
using colorbar might appropriate if there dozens of levels.
on other hand, if there few levels, using legend make more sense. in case, more convenient call plot once each level value, since matplotlib code makes legend set make 1 legend entry per plot:
import pandas pd import matplotlib.pyplot 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) level, dct in enumerate(result) val in dct.values()], columns=['level', 'size']) groups = df.groupby(['level']) fig, ax = plt.subplots() 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() 
Comments
Post a Comment