使用 for 循环绘图时如何跳过图例中的重复标签?
How can I skip repeated lablels in the legend when I plot using a for-loop?
import pandas as pd
import matplotlib.pyplot as plt
from random import random
DF = {"A":[(random(),random()),(random(),random())],
"B":[(random(),random()),(random(),random())],
"C":[(random(),random()),(random(),random())],
"D":[(random(),random()),(random(),random())]}
DF = pd.DataFrame(DF, index=["k=1","k=2"])
我的数据框的每一行都包含一个重复实验的观察结果,每一列代表一组受试者。条目是男性数据和女性数据的元组。所以我想绘制针对群体的观察结果,通过标记形状和颜色区分性别。我尝试了下面的方法,但产生的图例太长了。 如何只显示两个标签(男、女)?
plt.figure()
for row in DF.index:
plt.plot(DF.columns, [a for a,b in DF.loc[row,]], 'b.', label="Male")
plt.plot(DF.columns, [b for a,b in DF.loc[row,]], 'g+', label="Female")
plt.legend(loc="upper right")
plt.show()
顺便说一句,由于值非常接近,我可以在每个点的 x 坐标上添加一点随机噪声吗(就像 R 中的抖动)这样它们就可以更清晰?
让我们尝试在绘图之前重塑您的数据:
s = DF.unstack()
plot_df = pd.DataFrame(list(s.values), columns=['Male','Female'],
index=s.index.get_level_values(0))
styles = ['b.','g+']
plt.figure(figsize=(10,6))
for col,style in zip(plot_df.columns, styles):
plt.plot(plot_df.index, plot_df[col], style, label=col)
plt.legend(loc="upper right")
plt.show()
输出:
一个快速的解决方案是只为第一行添加标签。
要向 x-positions 添加抖动,您可以遍历生成的元素,获取它们的 x-positions,添加一些随机值并将它们放回原处。由于当前距离为 1,因此在 -0.4 和 0.4 之间添加一个数字应该可行。需要通过 relim
和 autoscale
.
重新计算 x 轴的范围
import pandas as pd
import matplotlib.pyplot as plt
from random import random
DF = {"A": [(random(), random()), (random(), random())],
"B": [(random(), random()), (random(), random())],
"C": [(random(), random()), (random(), random())],
"D": [(random(), random()), (random(), random())]}
DF = pd.DataFrame(DF, index=["k=1", "k=2"])
fig, ax = plt.subplots()
for row in DF.index:
ax.plot(DF.columns, [a for a, b in DF.loc[row,]], 'b.', label="Male" if row == "k=1" else None)
ax.plot(DF.columns, [b for a, b in DF.loc[row,]], 'g+', label="Female" if row == "k=1" else None)
for elements in ax.lines:
xs = elements.get_xydata()[:, 0] # get_xdata() returns strings, but get_xydata is fully numeric
jittered_xs = xs + np.random.uniform(-0.4, 0.4, xs.shape)
elements.set_xdata(jittered_xs)
ax.relim()
ax.autoscale(enable=True)
plt.legend(loc="upper right")
plt.show()
import pandas as pd
import matplotlib.pyplot as plt
from random import random
DF = {"A":[(random(),random()),(random(),random())],
"B":[(random(),random()),(random(),random())],
"C":[(random(),random()),(random(),random())],
"D":[(random(),random()),(random(),random())]}
DF = pd.DataFrame(DF, index=["k=1","k=2"])
我的数据框的每一行都包含一个重复实验的观察结果,每一列代表一组受试者。条目是男性数据和女性数据的元组。所以我想绘制针对群体的观察结果,通过标记形状和颜色区分性别。我尝试了下面的方法,但产生的图例太长了。 如何只显示两个标签(男、女)?
plt.figure()
for row in DF.index:
plt.plot(DF.columns, [a for a,b in DF.loc[row,]], 'b.', label="Male")
plt.plot(DF.columns, [b for a,b in DF.loc[row,]], 'g+', label="Female")
plt.legend(loc="upper right")
plt.show()
顺便说一句,由于值非常接近,我可以在每个点的 x 坐标上添加一点随机噪声吗(就像 R 中的抖动)这样它们就可以更清晰?
让我们尝试在绘图之前重塑您的数据:
s = DF.unstack()
plot_df = pd.DataFrame(list(s.values), columns=['Male','Female'],
index=s.index.get_level_values(0))
styles = ['b.','g+']
plt.figure(figsize=(10,6))
for col,style in zip(plot_df.columns, styles):
plt.plot(plot_df.index, plot_df[col], style, label=col)
plt.legend(loc="upper right")
plt.show()
输出:
一个快速的解决方案是只为第一行添加标签。
要向 x-positions 添加抖动,您可以遍历生成的元素,获取它们的 x-positions,添加一些随机值并将它们放回原处。由于当前距离为 1,因此在 -0.4 和 0.4 之间添加一个数字应该可行。需要通过 relim
和 autoscale
.
import pandas as pd
import matplotlib.pyplot as plt
from random import random
DF = {"A": [(random(), random()), (random(), random())],
"B": [(random(), random()), (random(), random())],
"C": [(random(), random()), (random(), random())],
"D": [(random(), random()), (random(), random())]}
DF = pd.DataFrame(DF, index=["k=1", "k=2"])
fig, ax = plt.subplots()
for row in DF.index:
ax.plot(DF.columns, [a for a, b in DF.loc[row,]], 'b.', label="Male" if row == "k=1" else None)
ax.plot(DF.columns, [b for a, b in DF.loc[row,]], 'g+', label="Female" if row == "k=1" else None)
for elements in ax.lines:
xs = elements.get_xydata()[:, 0] # get_xdata() returns strings, but get_xydata is fully numeric
jittered_xs = xs + np.random.uniform(-0.4, 0.4, xs.shape)
elements.set_xdata(jittered_xs)
ax.relim()
ax.autoscale(enable=True)
plt.legend(loc="upper right")
plt.show()