Матрица рассеяния, показывающая слишком много значений с плавающей запятой на графике - PullRequest
0 голосов
/ 15 февраля 2019

Я пытаюсь построить матрицу рассеяния, используя Python, но отметки на оси Y для верхнего левого графика содержат большое количество ненужных цифр.Я непосредственно строю график из панд с помощью функции scatter_matrix из pandas.plotting

Кроме того, я довольно новичок в Python, так что извините, если это глупый вопрос, но я просто не смог найти правильный ответ, подходящиймои потребности.

Я пытался использовать разные параметры форматирования оси, используя yaxis.set_major_formatter (не уверен, что это не сработает, потому что я строю графики из панд, но в любом случае не даю результатов), панд.set_option для настройки отображения.

from pandas.plotting import scatter_matrix
scatter_matrix(df, alpha=0.3, figsize=(9,9), diagonal='kde')
df:         Tesla Ret  Ford Ret    GM Ret
Date                                     
2012-01-03        NaN       NaN       NaN
2012-01-04  -0.013177  0.015274  0.004751
2012-01-05  -0.021292  0.025664  0.048227
2012-01-06  -0.008481  0.010354  0.033829
2012-01-09   0.013388  0.007686 -0.003490
2012-01-10   0.013578  0.000000  0.017513
2012-01-11   0.022085  0.022881  0.052926
2012-01-12   0.000708  0.005800  0.008173
2012-01-13  -0.193274 -0.008237 -0.015403
2012-01-17   0.167179 -0.001661 -0.003705
...

Я пытался использовать: plt.gca().yaxis.set_major_formatter(StrMethodFormatter('{x:,.2f}')) и ax.yaxis.set_major_formatter(FormatStrFormatter('%.2f')) после импорта соответствующих модулей, но безрезультатно.

Рисунок доступен здесь

Все остальное на рисунке так же, как и должно быть, только ось Y левого верхнего графика.Я хотел бы, чтобы он показывал одно или два десятичных значения, как и на остальной части рисунка.

Я был бы очень признателен за любую помощь, которая могла бы решить мою проблему.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

pandas.scatter_matrix страдает от неудачного выбора дизайна.То есть он отображает kde или гистограмму по диагонали к осям, которые показывают отметки для остальной части ряда.Затем для этого необходимо подделать метки и метки, чтобы они соответствовали данным.В ходе этого используются FixedLocator и FixedFormatter.Таким образом, формат тиклабел напрямую берется из строкового представления числа.

Я бы предложил здесь совершенно другой дизайн.То есть диагональные оси должны оставаться пустыми, и вместо этого используются двойные оси для отображения гистограммы или кривой kde.Следовательно, проблема из вопроса не может возникнуть.

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

def scatter_matrix(df, axes=None, **kw):
    n = df.columns.size
    diagonal = kw.pop("diagonal", "hist")

    if not axes:
        fig, axes = plt.subplots(n,n, figsize=kw.pop("figsize", None), 
                                 squeeze=False, sharex="col", sharey="row")
    else:
        flax = axes.flatten()
        fig = flax[0].figure
        assert len(flax) == n*n

    # no gaps between subplots
    fig.subplots_adjust(wspace=0, hspace=0)

    hist_kwds = kw.pop("hist_kwds",  {})
    density_kwds = kw.pop("density_kwds",  {})

    import itertools
    p = itertools.permutations(df.columns, r=2)
    n = itertools.permutations(np.arange(len(df.columns)), r=2)
    for (i,j), (y,x) in zip(n,p):
        axes[i,j].scatter(df[x].values, df[y].values, **kw)
        axes[i,j].tick_params(left=False, labelleft=False, 
                              bottom=False, labelbottom=False)

    diagaxes = []
    for i, c in enumerate(df.columns):

        ax = axes[i,i].twinx()
        diagaxes.append(ax)

        if diagonal == 'hist':
            ax.hist(df[c].values, **hist_kwds)

        elif diagonal in ('kde', 'density'):
            from scipy.stats import gaussian_kde
            y = df[c].values
            gkde = gaussian_kde(y)
            ind = np.linspace(y.min(), y.max(), 1000)
            ax.plot(ind, gkde.evaluate(ind), **density_kwds)

        if i!= 0:
            diagaxes[0].get_shared_y_axes().join(diagaxes[0], ax)
        ax.axis("off")


    for i,c in enumerate(df.columns):
        axes[i,i].tick_params(left=False, labelleft=False,
                               bottom=False, labelbottom=False)
        axes[i,0].set_ylabel(c)
        axes[-1,i].set_xlabel(c)
        axes[i,0].tick_params(left=True, labelleft=True)
        axes[-1,i].tick_params(bottom=True, labelbottom=True)


    return axes, diagaxes


df = pd.DataFrame(np.random.randn(1000, 4), columns=['A','B','C','D'])
axes,diagaxes = scatter_matrix(df, diagonal='kde', alpha=0.5)

plt.show()
0 голосов
/ 15 февраля 2019

PS: я отредактировал этот ответ, основываясь на проблеме, указанной @ ImportanceOfBeingEarnest (спасибо ему).Пожалуйста, прочитайте комментарии ниже ответа, чтобы понять, что я имею в виду.

Новое решение - получить отображаемые отметки для этой конкретной оси и отформатировать их с точностью до 2 десятичных знаков.

new_labels = [round(float(i.get_text()), 2) for i in axes[0,0].get_yticklabels()]
axes[0,0].set_yticklabels(new_labels)

enter image description here

СТАРЫЙ ОТВЕТ (Все еще сохраняется как история, поскольку вы увидите, что y-тики на рисунке, сгенерированном ниже, не верны)

Проблема в том, что вы используете ax объект для форматирования меток, но ax, возвращаемый из scatter_matrix, не является объектом с одной осью.Это объект, содержащий ось 9 (подфигура 3х3).Вы можете доказать это, если нанесете форму переменной axes.

axes = scatter_matrix(df, alpha=0.3, figsize=(9,9), diagonal='kde')
print (axes.shape)
# (3, 3)

Решением является или для перебора всех осей или для простого изменения форматирования для проблемного случая.PS: рисунок ниже не совпадает с вашим, потому что я только что использовал небольшой DataFrame, который вы разместили.

Ниже описано, как вы можете сделать это для всей оси y

from pandas.plotting import scatter_matrix
from matplotlib.ticker import FormatStrFormatter

axes = scatter_matrix(df, alpha=0.3, figsize=(9,9), diagonal='kde')
for ax in axes.flatten():
    ax.yaxis.set_major_formatter(FormatStrFormatter('%.2f')) 

enter image description here

В качестве альтернативы вы можете просто выбрать конкретную ось.Здесь ваша верхняя левая подфигура может быть доступна с помощью axes[0,0]

axes[0,0].yaxis.set_major_formatter(FormatStrFormatter('%.2f'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...