inconsistency between DataFrame.plot.scatter and D

2019-08-19 00:00发布

The following example illustrates a strange difference between scatter- and density plots from pandas DataFrame .. or possibly my lack of understanding:

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

n = 25
df = pd.DataFrame({'x': np.random.randn(n), 'y': np.random.randn(n), 'season': np.random.choice(['winter', 'summer'], n)})

plot = df.plot.scatter(x='x', y='y')
plot.get_figure().savefig("test_scatter_all.png")
for s in ['winter', 'summer']:
    sdf = df[df['season'] == s]
    plot = sdf.plot.scatter(x='x', y='y')
    plot.get_figure().savefig("test_scatter_" + s + ".png")

plt.clf()

plot = df['y'].plot.density()
plot.get_figure().savefig("test_density_all.png")
for s in ['winter', 'summer']:
    sdf = df[df['season'] == s]
    plot = sdf['y'].plot.density()
    plot.get_figure().savefig("test_density_" + s + ".png")

What surprised me is that the density plots are additive in the sense that the winter-chart includes two densities ('all' and winter) and the summer-chart includes all three densities. On the other hand, the scatter plots includes only their own points, i.e., winter-values in winter-plots etc.
Also, without the plt.clf() command, the density plots would also include points from the last scatter plot (summer).

Why the difference between the two plot types? And does it mean that I should always use plt.clf() before starting a new plot?

And, as a side note, does it actually make any sense to use the plot object the way I do? I see that I can generate the first plot with

df.plot.scatter(x='x', y='y')
plt.savefig("test_scatter_all.png")

as well, so is there any point in capturing the output of the plot() methods? And does it mean that there is always only one active figure object that the plot() methods write to?

1条回答
祖国的老花朵
2楼-- · 2019-08-19 00:30

The inconsistency is not between density and scatter, but between the plotting method of a dataframe and the plotting method of a series:

  • A series, Series.plot, is plotted to the active axes, if there is one, else a new figure is created.

  • A dataframe, DataFrame.plot, is plotted to a new figure, independent on whether there already exists one.

Example:

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

df = pd.DataFrame({'x': np.random.randn(25), 'y': np.random.randn(25), 
                   'season': np.random.choice(['red', 'gold'], 25)})

# This plots the dataframe, and creates two figures
for s in ['red', 'gold']:
    sdf = df[df['season'] == s]
    plot = sdf.plot(kind="line",color=s)
plt.show() 

# This plots a series, and creates a single figure  
for s in ['red', 'gold']:
    sdf = df[df['season'] == s]
    plot = sdf["y"].plot(kind="line",color=s)
plt.show()

Here, sdf.plot creates two figures, while sdf["y"].plot plots to the same axes.


If the problem is to keep a previously plotted density in the plot, you may plot this density, add another one, save the figure and finally remove the second plot, such that you end up with the first density plot, ready to plot something else to it.

import numpy as np
import pandas as pd

df = pd.DataFrame({'x': np.random.randn(25), 'y': np.random.randn(25), 
                   'season': np.random.choice(['red', 'gold'], 25)})

ax = df['y'].plot.density()
for s in ['red', 'gold']:
    sdf = df[df['season'] == s]
    sdf["y"].plot.density(color=s)
    ax.get_figure().savefig("test_density_" + s + ".png")
    ax.lines[-1].remove()
查看更多
登录 后发表回答