matplotlib:共享轴上具有对数刻度的不可读散点图和直方图 [英] matplotlib: unreadable scatter plots and histograms on shared axis with logscale

查看:33
本文介绍了matplotlib:共享轴上具有对数刻度的不可读散点图和直方图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在绘制一些包含大量数据点的散点图.在某些时候,一半的情节只是纯色,您无法很好地看到密度.因此,我想将数据投影"到轴上并显示直方图.

I'm plotting a couple of scatter plots with a lot of data points. At some point half the plot is just solid color and you cannot see the density very well. So I want to "project" the data onto the axis and display a histogram.

我写了一个小函数来做到这一点.对于轴 ax 上的绘图,它绘制了熊猫DataFrame frame 的字段 column_x column_y .如果给出了 one_track_frame,它也会在上面绘制.要添加标题和标签等,可以使用 ax 对象作为参数传递 lambda.

I wrote a little function that does that. To a plot on axis ax it plots the fields column_x vs column_y of the pandas DataFrame frame. If one_track_frame is given, it is also plotted on top of that. To add add a title and labels etc. a lambda can be passed with the ax object as parameter.

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import pandas as pd

def projection_plot(ax, frame, column_x, column_y, frame_one_track=None, commands=None, bins=100):
    ax.scatter(frame[column_x], frame[column_y], label="one track", marker='x')

    divider = make_axes_locatable(ax)
    ax_hist_x = divider.append_axes("top", 1.2, pad=0.1, sharex=ax)
    for tl in ax_hist_x.get_xticklabels():
        tl.set_visible(False)
    ax_hist_x.hist(frame[column_x], bins=50)

    ax_hist_y = divider.append_axes("right", 1.2, pad=0.1, sharey=ax)
    for tl in ax_hist_y.get_yticklabels():
        tl.set_visible(False)
    ax_hist_y.hist(frame[column_y], orientation='horizontal', bins=bins)

    if frame_one_track is not None:
        ax.scatter(frame_one_track[column_x], frame_one_track[column_y], label="two tracks", marker='.')
        ax_hist_x.hist(frame_one_track[column_x], bins=bins)
        ax_hist_y.hist(frame_one_track[column_y], orientation='horizontal', bins=bins)

    if commands is not None:
        commands(ax)

如果我现在绘制一些随机数据,则一切看起来都很好,并且符合预期.

If I now plot some random data, everything looks fine and as intended.

df = pd.DataFrame(np.random.randn(1000, 3)*1000, columns=["a", "b", "c"])
cut = df["c"] < 20
frame1 = df[cut]
frame2 = df[~cut]

plt.figure(figsize=(6,6))
projection_plot(plt.subplot(), frame1, "a", "b", frame2, commands=lambda ax: (
    ax.legend(),
    ax.set_title("Random Values", y=1.4),
    ax.set_xlabel("column 0"),
    ax.set_ylabel("column 1")))

如果我现在尝试将任一(或两个)轴的比例设置为 log,则会出现问题并且情节变得不可读:

If I now try to set the scales of either (or both) axis to log, something breaks and the plot becomes unreadable:

plt.figure(figsize=(6,6))
projection_plot(plt.subplot(), frame1, "a", "b", frame2, commands=lambda ax: (
    ax.legend(),
    ax.set_yscale('log'),
    ax.set_title("Random Values", y=1.4),
    ax.set_xlabel("column 0"),
    ax.set_ylabel("column 1")))

在我的某些数据集中,它似乎工作正常,而对于其他数据集,则类似于此随机数据.我该如何解决?

In some of my data sets it seemed to work fine, while for others it breaks like with this random data. How can I fix this?

另外:由于我对 Python 比较陌生,这种编码风格好吗?传递多行 lambda 以进行进一步配置?我有一种感觉,Ruby 块毁了我……

Also: Since I'm relatively new to Python, is this good coding style? Passing multi line lambdas for further configuration? I have the feeling that Ruby blocks ruined me…

推荐答案

我不完全知道失败的原因,我可以想象问题与数据范围小于0且对数刻度不相关的数据有关定义.

I do not exactly know the reason why this fails, I could imagine that the problem is related to the data ranging to below 0 for which a log scale is not defined.

无论如何,您都需要手动设置图的限制,

In any case you would need to set the limits of the plot manually,

ax.set_yscale('log')
ax.set_ylim(1,None)

可能您想改用 symlog 标尺.

ax.set_yscale('symlog')

在这种情况下,无需进行限制调整.

In this case no limit adjustment needs to be made.

这篇关于matplotlib:共享轴上具有对数刻度的不可读散点图和直方图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆