所以我有 2 个数据框,每个都有多个列:
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
0.11 | 1.12 | 12.32 | ||
1.48 | 0.03 | 0.32 | 17.85 | |
0.56 | 0.95 | 8.35 | ||
0.09 | 2.31 | 0.32 | 1.04 | 5.46 |
另一张与此类似,填充了一些其他数据。我需要在 1 个图上绘制这 2 个数据框。每列都是不同的 x 轴索引值。我正在使用 pandas.DataFrame.boxplot() 方法,因为它是真正绘制数据而不跳过任何内容的唯一方法(matplotlib.boxplot() 似乎只绘制了数据的一部分,不知道为什么)。
问题在于,依次调用多个 df.boxplot() 会导致错误:
File "analysis_script.py", line 387, in <module>
df.boxplot()
File "pandas\plotting\_core.py", line 516, in boxplot_frame
return plot_backend.boxplot_frame(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "pandas\plotting\_matplotlib\boxplot.py", line 458, in boxplot_frame
ax = boxplot(
^^^^^^^^
File "pandas\plotting\_matplotlib\boxplot.py", line 437, in boxplot
result = plot_group(columns, data.values.T, ax, **kwds)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "bpandas\plotting\_matplotlib\boxplot.py", line 376, in plot_group
assert remainder == 0, remainder
^^^^^^^^^^^^^^
AssertionError: 1
这是我的代码部分:
match index:
case 0:
fig, ax = plt.subplots()
df.boxplot()
case 1:
df.boxplot()
min_y = min_y_8h - 0.25 * abs(min_y_8h)
max_y = max_y_8h + 1.25 * abs(max_y_8h)
x_ticks = plt.xticks()[0]
x_labels = [str(int(tick)) for tick in x_ticks if int(tick) % 3 == 0]
plt.xticks(x_ticks[x_ticks % 3 == 0], x_labels, rotation=45)
plt.xlim(2.5, 23.5)
plt.ylim(min_y, max_y)
plt.show()
plt.close()
它在循环中运行,因此 df 变量在每次迭代中都是不同的 df,并且索引变量有许多功能,在本例中,它用于监视正在绘制哪些数据。
AssertionError: 1
可能是由于您使用循环创建的不同数据帧之间的列数不匹配。
我尝试重现该问题,并且使用几个最小的数据帧确实遇到了相同的问题。我试图解决这个问题 - 使用 matplotlib
的箱线图从同一轴上的多个数据帧绘制箱线图,它似乎可以解决问题:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# random dfs
df1 = pd.DataFrame(np.random.rand(10, 4), columns=['A', 'B', 'C', 'D'])
df2 = pd.DataFrame(np.random.rand(10, 3), columns=['E', 'F', 'G'])
dfs = [df1, df2]
# Create a figure and axes outside the loop
fig, ax = plt.subplots()
# Initial position for the first dataframe's boxplot
position = 1
for df in dfs:
# plot the dataframe using Matplotlib's boxplot
ax.boxplot([df[col].dropna() for col in df.columns], positions=range(position, position + len(df.columns)))
# update position
position += len(df.columns)
ax.set_xticks(range(1, position))
ax.set_xticklabels(['A', 'B', 'C', 'D', 'E', 'F', 'G'], rotation=45)
ax.set_xlim(0.5, position - 0.5)
plt.show()
我们不知道循环之外发生了什么,但使用这种方法它应该看起来像这样。这不是一个有效的示例,因为我没有您使用的数据,但它是基于您的代码的骨架:
import matplotlib.pyplot as plt
# Assuming 'dfs' is a list of your dataframes
dfs = [...]
# Initialize the position for the first boxplot
position = 1
for index, df in enumerate(dfs):
match index:
case 0:
fig, ax = plt.subplots()
# Plot using Matplotlib's boxplot
ax.boxplot([df[col].dropna() for col in df.columns], positions=range(position, position + len(df.columns)))
# Update the position for the next dataframe
position += len(df.columns)
case 1:
# Plot using Matplotlib's boxplot
ax.boxplot([df[col].dropna() for col in df.columns], positions=range(position, position + len(df.columns)))
# Update the position for the next dataframe
position += len(df.columns)
# Your additional settings
min_y = min_y_8h - 0.25 * abs(min_y_8h)
max_y = max_y_8h + 1.25 * abs(max_y_8h)
x_ticks = ax.get_xticks()
x_labels = [str(int(tick)) for tick in x_ticks if int(tick) % 3 == 0]
ax.set_xticks(x_ticks[x_ticks % 3 == 0])
ax.set_xticklabels(x_labels, rotation=45)
ax.set_xlim(2.5, position - 0.5)
ax.set_ylim(min_y, max_y)
# Show the plot
plt.show()
plt.close()
当您尝试从多个 dfs 生成单个图时,我还将 show()
和
close()
放在循环之外,这更有意义。