Matplotlib'de tik ölçeği 2'nin gücü olarak nasıl ayarlanır? [çiftleme]

Dec 16 2020

Xtick değerleri 2'nin kuvvetinde büyüyen bir rakam çizmek istiyorum.

Örneğin,

import pandas as pd
data = pd.DataFrame({
    'x': [2, 4, 8, 16, 32, 64],
    'y': [1, 2, 3, 4, 5, 6]
})

Beklediğim şey böyle bir rakam

Yukarıdaki örnek gibi düzenli veriler için, bu veri çerçevesinde sadece x21 ~ 6 yardımcı sütun oluşturabilir ve ardından şeklin xticklabels'ını 2 ^ 1 ~ 2 ^ 6 olarak ayarlayabilirim. Ancak bu geçici çözüm, 3, 7 veya 30 gibi diğer değerlere sahip durumlar için geçerli değildir.

Görünüşe göre matplotlib yalnızca bir günlük ölçeğini destekliyor. Güç ölçeği 2 olan bir tik işaretine nasıl ulaşabilirim?

Yanıtlar

max Dec 16 2020 at 17:20

Bu özellikle hileli bir sorudur (^^ olmasını beklemiyordum).

Tamam, okumak için birkaç ipucu ile başlayalım: x / y ölçeğini ayarlamak istiyorsunuz: .matplotlib.axes.Axes.set_yscale () . Birkaç standart ölçek varken (varsayılan değer açıktır 'liner', özel bir ölçek belirlenebilir. İşte bazı güzel örnekler.

Temel olarak, ileri dönüşüm ve bunun tersi ile iki işlev tanımlarsınız . Daha sonra onay işaretlerini doğru şekilde ayarlamanız gerekir (çünkü dönüşümü çizimden sonra uyguladığınız için , işaretler aynı kalır (ancak dönüşüm nedeniyle aynı konumda değil) Bunun için iki seçenek vardır:

  • işaretlerin manuel olarak ayarlanması matplotlib.axes.Axes.set_xticks()veya
  • ayarlayarak locator ekseninin: matplotlib.axes.Axes.xaxis.set_major_locator(). Izgaralar kullanıyorsanız bu önerilir. Ancak bilgim sınırlı olduğundan, daha ayrıntılı bir açıklamayı takdir ediyorum (çünkü artık bu özelliği de merak ediyorum ^^)

Ve şimdi işin zor kısmı geliyor: tik etiketlerini bir '2^x'. Onları açık bir şekilde dizeler olarak belirlemekten daha iyi bir fikirle karşılaşmadım. Görünüşe göre genel format yalnızca sınırlı sınırlar içinde değiştirilebilir, bakın matplotlib.pyplot.ticklabel_format(), bilimsel bir gösterimin kullanılıp kullanılmayacağını ve ne zaman kullanılacağını seçebilir (yani '10^x'sağ altta a göstererek ). Bunun için daha genel bir çözüm olup olmadığını bana bildirin.

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import FixedLocator

# create dummy data
df = pd.DataFrame({
    'x': [2**x for x in range(1,10)],
    'y': list(range(1,10))
})

def forward(x):
    return np.log2(x)


def inverse(x):
    return 2**x

# open figure
fig, ax = plt.subplots(2,2)
axs = ax.flatten()
for i in range(0,4):
    # plot data
    axs[i].plot(df['x'],df['y'])
    if i > 0:
        # set scale function
        axs[i].set_xscale('function', functions=(forward,inverse))
    if i > 1:
        # set ticks
        # - OPTION 1
        axs[i].set_xticks(df['x'])
        # - OPTION 2
      axs[i].xaxis.set_major_locator(FixedLocator(2**np.arange(1,10)))
    if i > 2:
        # est tick labels
        axs[i].set_xticklabels( [f"2^{j:.0f}" for j in np.log2(df['x'])] )

plt.show()