#python #pandas #matplotlib
#python #pandas #matplotlib
Вопрос:
Я пытаюсь передать функцию, которая отображает различные объекты для каждой уникальной метки. Используя df ниже, A-D
используются для построения различных объектов. Затем я передаю каждое уникальное значение в label
функцию.
Я надеюсь передать что-то более эффективное, чем вызов функции для каждого уникального элемента в списке. Перебор списка для получения отдельной цифры для каждого уникального значения в label
. Используя ниже, это должно быть 3 (X,Y,Z)
.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import random
def plot(dfs, label):
fig, ax = plt.subplots()
for l in label:
df = dfs[dfs['label'] == l]
x1 = df['A']
y1 = df['B']
x2 = df['C']
y2 = df['D']
plt.scatter(x1, y1, c = 'orange', marker = 'o', zorder = 3)
plt.scatter(x2, y2, c = 'green', marker = 'o', zorder = 2)
ax.plot([x1,x2],[y1,y2], color = 'k', linestyle = '-', linewidth = 1)
plt.show()
np.random.seed(2020)
df = pd.DataFrame(np.random.randint(0,20,size=(20, 4)), columns=list('ABCD'))
labels = df['A'].apply(lambda x: random.choice(['X', 'Y', 'Z']) )
df['label'] = labels
unq_label = df['label'].unique()
figs = df.groupby('label').apply(plot,unq_label)
Ответ №1:
@r-beginners уже решил проблему. В моем посте я также решу эту проблему, используя тот же (возможно, единственный) способ, но с другим Dataframe
для лучшей визуализации.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import random
def plot(dfs, label):
label = sorted(label)
fig, ax = plt.subplots(nrows=1,ncols=len(label),figsize=(12,6))
for ind,l in enumerate(label):
df = dfs[dfs['label'] == l]
x1 = df['A']
y1 = df['B']
x2 = df['C']
y2 = df['D']
ax[ind].scatter(x1, y1, c = 'orange', marker = 'o', zorder = 3,)
ax[ind].scatter(x2, y2, c = 'green', marker = 'o', zorder = 2,)
ax[ind].plot([x1,x2],[y1,y2], color = 'k', linestyle = '-', linewidth = 1,)
ax[ind].set_title('class %s' % l)
ax[ind].set_ylim(-11,21)
plt.show()
np.random.seed(2020)
x,y,z = np.random.randint(0,5,size=(5, 4)),np.random.randint(-10,0,size=(5, 4)),np.random.randint(10,20,size=(5, 4)),
data = np.vstack((x,y,z))
df = pd.DataFrame(data, columns=list('ABCD'))
df['label'] = ['X'] *5 ['Y'] * 5 ['Z'] * 5
unq_label = df['label'].unique()
plot(df, unq_label)
Выходная цифра
Обновить
Чтобы отображать разные метки на разных рисунках, а не на подзаголовках, вы можете попробовать приведенный ниже код. Идея состоит в том, чтобы создать новую фигуру для каждой метки.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import random
def plot(dfs, label):
label = sorted(label)
for ind,l in enumerate(label):
fig = plt.figure(ind)
df = dfs[dfs['label'] == l]
x1 = df['A']
y1 = df['B']
x2 = df['C']
y2 = df['D']
plt.scatter(x1, y1, c = 'orange', marker = 'o', zorder = 3,)
plt.scatter(x2, y2, c = 'green', marker = 'o', zorder = 2,)
plt.plot([x1,x2],[y1,y2], color = 'k', linestyle = '-', linewidth = 1,)
plt.title('class %s' % l)
plt.ylim(-11,21)
plt.show()
np.random.seed(2020)
x,y,z = np.random.randint(0,5,size=(5, 4)),np.random.randint(-10,0,size=(5, 4)),np.random.randint(10,20,size=(5, 4)),
data = np.vstack((x,y,z))
df = pd.DataFrame(data, columns=list('ABCD'))
df['label'] = ['X'] *5 ['Y'] * 5 ['Z'] * 5
unq_label = df['label'].unique()
plot(df, unq_label)
Комментарии:
1. Я надеюсь получить выходные данные. Итак, отдельная цифра для каждой уникальной метки. Не отдельные подзаголовки в пределах одного рисунка.
2. это то, что я искал
df.groupby('label').apply(plot,unq_label)
3. @jonboy Я понимаю, см. Мой обновленный пост, идея состоит в том, чтобы создать новую фигуру для каждой уникальной метки.
Ответ №2:
По мере развития вопроса я изменил код для текущей проблемы. axes[]
чтобы сделать его массивом. Так ли это задумано?
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import random
def plot(dfs, label):
fig, axes = plt.subplots(1,3)
for i,l in enumerate(label):
df = dfs[dfs['label'] == l]
x1 = df['A']
y1 = df['B']
x2 = df['C']
y2 = df['D']
axes[i].scatter(x1, y1, c = 'orange', marker = 'o', zorder = 3)
axes[i].scatter(x2, y2, c = 'green', marker = 'o', zorder = 2)
axes[i].plot([x1,x2],[y1,y2], color = 'k', linestyle = '-', linewidth = 1)
fig.subplots_adjust(wspace=0.5)
plt.show()
np.random.seed(2020)
df = pd.DataFrame(np.random.randint(0,20,size=(20, 4)), columns=list('ABCD'))
labels = df['A'].apply(lambda x: random.choice(['X', 'Y', 'Z']) )
df['label'] = labels
unq_label = df['label'].unique()
plot(df, unq_label)
Комментарии:
1. Я получаю сообщение об ошибке в строке :
ax.plot([Ax,Cx],[By,Dy], color = 'k', linestyle = '-', linewidth = 1)
.Error: KeyError: 0
2.
print(df)
чтобы увидеть, существуют ли данные. В этом случае легче отлаживать, если вы установитеnp.random.seed(2020)
значение до генерации случайного числа. Это не генерирует ошибку в моей среде. Вы скопировали весь код?3. Да, данные существуют. Я ввел начальное значение. Я думаю, что это количество элементов на этикетке. Если я увеличу длину df до 1000 значений, это сработает. Но я надеюсь построить отдельные цифры для каждой уникальной метки.
4. Я не уверен, как меняется ситуация с количеством данных. Кроме того, если вы хотите пометить его, вы можете присвоить ему
ax.text()
значение илиax.annotate()
, но если это большое число, это может сделать график более запутанным.