Как установить шкалу тика как степень 2 в matplotlib? [дубликат]
Я хочу построить фигуру, значения xtick которой растут со степенью 2.
Например,
import pandas as pd
data = pd.DataFrame({
'x': [2, 4, 8, 16, 32, 64],
'y': [1, 2, 3, 4, 5, 6]
})
Я ожидаю такой фигуры,

Для аккуратных данных, подобных приведенному выше образцу, я могу просто создать вспомогательный столбец x2
размером 1 ~ 6 в этом фрейме данных, а затем установить xticklabels рисунка на 2 ^ 1 ~ 2 ^ 6. Однако этот обходной путь не применяется к ситуациям с другими значениями, такими как 3, 7 или 30.
Кажется, что matplotlib поддерживает только шкалу журнала. Как добиться отметки со шкалой мощности 2?
Ответы
Это особенно сложный вопрос (которого я не ожидал ^^).
Хорошо, давайте начнем с нескольких советов для чтения: вы хотите установить масштаб x / y: .matplotlib.axes.Axes.set_yscale () . Хотя есть несколько стандартных масштабов (очевидно 'liner'
, по умолчанию , можно установить собственный масштаб. Вот несколько хороших примеров.
По сути, вы определяете две функции с прямым преобразованием и с обратным ему. После этого вам необходимо правильно установить метки (поскольку вы применяете преобразование после построения графика, метки остаются прежними (но не в том же положении из-за преобразования). Для этого есть два варианта:
- установка галочки вручную
matplotlib.axes.Axes.set_xticks()
, или - установив локатор оси:
matplotlib.axes.Axes.xaxis.set_major_locator()
. Это рекомендуется, если вы используете сетки. Но поскольку мои знания ограничены, я ценю более подробное объяснение (потому что теперь мне также интересно узнать об этой функции ^^)
А теперь самое сложное: форматирование меток для представления файла '2^x'
. Я не нашел лучшей идеи, чем явно задавать их как строки. Кажется, что можно изменить общий формат только в ограниченных пределах, см. matplotlib.pyplot.ticklabel_format(), Где можно выбрать, следует ли и когда использовать научную нотацию (например, отображение символа '10^x'
в правом нижнем углу). Сообщите мне, есть ли для этого более общее решение.
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()