绘制连接两个 swarmplots 的各个数据点的彩色线
Plotting colored lines connecting individual data points of two swarmplots
我有:
import numpy as np
import pandas as pd
import seaborn as sb
import matplotlib.pyplot as plt
# Generate random data
set1 = np.random.randint(0, 40, 24)
set2 = np.random.randint(0, 100, 24)
# Put into dataframe and plot
df = pd.DataFrame({'set1': set1, 'set2': set2})
data = pd.melt(df)
sb.swarmplot(data=data, x='variable', y='value')
用 seaborn 的 swarmplot 函数绘制的两个随机分布:
我希望两个分布的各个图都用彩色线连接,以便数据框中第 1 组的第一个数据点与第 2 组的第一个数据点连接。
我意识到如果没有 seaborn,这可能会相对简单,但我想保留各个数据点不重叠的特性。
有什么方法可以访问 seaborn swarmfunction 中的各个地块坐标吗?
当然,这是可能的(但你真的不想)。
seaborn.swarmplot
returns 轴实例(此处:ax
)。您可以获取 children ax.get_children
以获取所有绘图元素。您将看到对于每组点,都有一个 PathCollection
类型的元素。您可以使用 PathCollection.get_offsets()
方法确定 x, y 坐标。
不建议你这样做!疯狂就是这样。
我建议您查看源代码 (found here),并从 _SwarmPlotter
派生您自己的 _PairedSwarmPlotter
并根据您的需要更改 draw_swarmplot
方法.
编辑:感谢@Mead,他在 2021 年 8 月 23 日之前指出了我的 post 中的一个错误(我忘记对先前版本中的位置进行排序)。
我试了一下 给出了很好的答案,尽管他这么说
Madness lies this way
...我实际上认为它非常简单并且产生了不错的结果:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
# Generate random data
rng = np.random.default_rng(42)
set1 = rng.integers(0, 40, 5)
set2 = rng.integers(0, 100, 5)
# Put into dataframe
df = pd.DataFrame({"set1": set1, "set2": set2})
print(df)
data = pd.melt(df)
# Plot
fig, ax = plt.subplots()
sns.swarmplot(data=data, x="variable", y="value", ax=ax)
# Now connect the dots
# Find idx0 and idx1 by inspecting the elements return from ax.get_children()
# ... or find a way to automate it
idx0 = 0
idx1 = 1
locs1 = ax.get_children()[idx0].get_offsets()
locs2 = ax.get_children()[idx1].get_offsets()
# before plotting, we need to sort so that the data points
# correspond to each other as they did in "set1" and "set2"
sort_idxs1 = np.argsort(set1)
sort_idxs2 = np.argsort(set2)
# revert "ascending sort" through sort_idxs2.argsort(),
# and then sort into order corresponding with set1
locs2_sorted = locs2[sort_idxs2.argsort()][sort_idxs1]
for i in range(locs1.shape[0]):
x = [locs1[i, 0], locs2_sorted[i, 0]]
y = [locs1[i, 1], locs2_sorted[i, 1]]
ax.plot(x, y, color="black", alpha=0.1)
它打印:
set1 set2
0 3 85
1 30 8
2 26 69
3 17 20
4 17 9
你可以看到数据在图中是对应链接的。
我有:
import numpy as np
import pandas as pd
import seaborn as sb
import matplotlib.pyplot as plt
# Generate random data
set1 = np.random.randint(0, 40, 24)
set2 = np.random.randint(0, 100, 24)
# Put into dataframe and plot
df = pd.DataFrame({'set1': set1, 'set2': set2})
data = pd.melt(df)
sb.swarmplot(data=data, x='variable', y='value')
用 seaborn 的 swarmplot 函数绘制的两个随机分布:
我希望两个分布的各个图都用彩色线连接,以便数据框中第 1 组的第一个数据点与第 2 组的第一个数据点连接。 我意识到如果没有 seaborn,这可能会相对简单,但我想保留各个数据点不重叠的特性。 有什么方法可以访问 seaborn swarmfunction 中的各个地块坐标吗?
当然,这是可能的(但你真的不想)。
seaborn.swarmplot
returns 轴实例(此处:ax
)。您可以获取 children ax.get_children
以获取所有绘图元素。您将看到对于每组点,都有一个 PathCollection
类型的元素。您可以使用 PathCollection.get_offsets()
方法确定 x, y 坐标。
不建议你这样做!疯狂就是这样。
我建议您查看源代码 (found here),并从 _SwarmPlotter
派生您自己的 _PairedSwarmPlotter
并根据您的需要更改 draw_swarmplot
方法.
编辑:感谢@Mead,他在 2021 年 8 月 23 日之前指出了我的 post 中的一个错误(我忘记对先前版本中的位置进行排序)。
我试了一下
Madness lies this way
...我实际上认为它非常简单并且产生了不错的结果:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
# Generate random data
rng = np.random.default_rng(42)
set1 = rng.integers(0, 40, 5)
set2 = rng.integers(0, 100, 5)
# Put into dataframe
df = pd.DataFrame({"set1": set1, "set2": set2})
print(df)
data = pd.melt(df)
# Plot
fig, ax = plt.subplots()
sns.swarmplot(data=data, x="variable", y="value", ax=ax)
# Now connect the dots
# Find idx0 and idx1 by inspecting the elements return from ax.get_children()
# ... or find a way to automate it
idx0 = 0
idx1 = 1
locs1 = ax.get_children()[idx0].get_offsets()
locs2 = ax.get_children()[idx1].get_offsets()
# before plotting, we need to sort so that the data points
# correspond to each other as they did in "set1" and "set2"
sort_idxs1 = np.argsort(set1)
sort_idxs2 = np.argsort(set2)
# revert "ascending sort" through sort_idxs2.argsort(),
# and then sort into order corresponding with set1
locs2_sorted = locs2[sort_idxs2.argsort()][sort_idxs1]
for i in range(locs1.shape[0]):
x = [locs1[i, 0], locs2_sorted[i, 0]]
y = [locs1[i, 1], locs2_sorted[i, 1]]
ax.plot(x, y, color="black", alpha=0.1)
它打印:
set1 set2
0 3 85
1 30 8
2 26 69
3 17 20
4 17 9
你可以看到数据在图中是对应链接的。