想用log10比例尺的x轴绘制多个Pandas数据帧的直方图

10

我在Pandas数据框中拥有浮点数数据。每一列代表一个变量(它们具有字符串名称),每一行代表一组值(行具有不重要的整数名称)。

>>> print data
0      kppawr23    kppaspyd
1      3.312387   13.266040
2      2.775202    0.100000
3    100.000000  100.000000
4    100.000000   39.437420
5     17.017150   33.019040
...

我想为每一列绘制直方图。我已经使用数据框的hist方法取得了最好的结果:

data.hist(bins=20)

但我希望每个直方图的x轴都是对数10比例尺。并且每个箱子也要使用对数10比例尺,但使用bins=np.logspace(-2,2,20)很容易实现。

一种解决方法可能是在绘图之前对数据进行log10变换,但我尝试过的方法不起作用,

data.apply(math.log10)

data.apply(lambda x: math.log10(x))

给我一个浮点数错误。

    "cannot convert the series to {0}".format(str(converter)))
TypeError: ("cannot convert the series to <type 'float'>", u'occurred at index kppawr23')
1个回答

7

你可以使用

ax.set_xscale('log')

data.hist() 返回一组轴。您需要为每个轴调用 ax.set_xscale('log'),以使每个轴都对数缩放。


例如,
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
np.random.seed(2015)

N = 100
arr = np.random.random((N,2)) * np.logspace(-2,2,N)[:, np.newaxis]
data = pd.DataFrame(arr, columns=['kppawr23', 'kppaspyd'])

bins = np.logspace(-2,2,20)
axs = data.hist(bins=bins)
for ax in axs.ravel():
    ax.set_xscale('log')

plt.gcf().tight_layout()
plt.show()

产量

enter image description here


顺便提一下,要对数据框中的每个值取对数,您可以使用data
logdata = np.log10(data)

因为NumPy ufuncs(例如np.log10)可以应用于pandas DataFrames,因为它们对DataFrame中的所有值elementwise操作

data.apply(math.log10)无法工作,因为apply尝试将整个列(Series)的值传递给math.log10math.log10仅期望标量值。

data.apply(lambda x: math.log10(x))由于与data.apply(math.log10)相同的原因而失败。此外,如果data.apply(func)data.apply(lambda x: func(x))都是可行的选项,则应首选第一个,因为lambda函数只会使调用稍微慢一些。

您可以使用data.apply(np.log10),因为NumPy ufuncnp.log10可以应用于Series,但没有理由这样做,因为np.log10(data)有效。

您也可以使用data.applymap(math.log10),因为applymap会逐个调用data中的每个值上的math.log10。但这比在整个DataFrame上调用等效的NumPy函数np.log10要慢得多。尽管如此,了解applymap仍然是有价值的,以防需要调用一些不是ufunc的自定义函数。

谢谢!我不知道ravel()。我也没有深入研究过numpy。我一直在尝试专注于pandas,因为它非常快速地读取大型数据集。 - Simon Woodward
顺便问一下,有什么方法可以加速吗?我有219个直方图要生成,这需要几分钟(在PyCharm社区版中以调试模式运行)。 - Simon Woodward
我能否以某种方式将tight_layout应用于data.hist? - Simon Woodward
1
你可以使用 plt.gcf().tight_layout(); 我已经编辑了上面的帖子。你可以尝试使用 multiprocessing 模块将工作分配给处理器以加快速度。Python Module of the Week 的 multiprocessing 教程 是一个不错的起点。 - unutbu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接