使用python绘制箱线图时如何处理NaN值

Posted

技术标签:

【中文标题】使用python绘制箱线图时如何处理NaN值【英文标题】:How to deal with NaN value when plot boxplot using python 【发布时间】:2022-01-16 23:56:10 【问题描述】:

我正在使用 matplotlib 绘制一个方框图,但有一些缺失值 (NaN)。然后我发现它没有在具有 NaN 值的列中显示方框图。 你知道如何解决这个问题吗? 这是代码。

import numpy as np
import matplotlib.pyplot as plt

#==============================================================================
# open data
#==============================================================================
filename='C:\\Users\\liren\\OneDrive\\Data\\DATA in the first field-final\\ks.csv'

AllData=np.genfromtxt(filename,delimiter=";",skip_header=0,dtype='str')

TreatmentCode = AllData[1:,0]
RepCode = AllData[1:,1]
KsData= AllData[1:,2:].astype('float')
DepthHeader = AllData[0,2:].astype('float')
TreatmentUnique = np.unique(TreatmentCode)[[3,1,4,2,8,6,9,7,0,5,10],]
nT = TreatmentUnique.size#nT=number of treatments
#nD=number of deepth;nR=numbers of replications;nT=number of treatments;iT=iterms of treatments
nD = 5
nR = 6
KsData_3D = np.zeros((nT,nD,nR)) 

for iT in range(nT):
    Treatment = TreatmentUnique[iT]

    TreatmentFilter = TreatmentCode == Treatment

    KsData_Filtered = KsData[TreatmentFilter,:]
    
    KsData_3D[iT,:,:] = KsData_Filtered.transpose()iD = 4
                      
fig=plt.figure()
ax = fig.add_subplot(111)
plt.boxplot(KsData_3D[:,iD,:].transpose())
ax.set_xticks(range(1,nT+1))
ax.set_xticklabels(TreatmentUnique)
ax.set_title(DepthHeader[iD])

这是最终的数字,有些治疗方法缺少方框。

【问题讨论】:

替换NaN值或过滤掉没有Nan的数据 @ERIC 请使用tour,阅读How to Ask 和minimal reproducible example。然后更新您的问题以提供所需的详细信息,以便有人可以帮助您。 嗯,这不是真正的minimal reproducible example,但至少它显示了问题。下次,请在代码中编造一些任意数据,使示例完整且可验证。 【参考方案1】:

您可以先从数据中删除NaNs,然后绘制过滤后的数据。

为此,您可以先使用np.isnan(data) 找到NaNs,然后使用~ operator 对该布尔数组执行按位取反。使用它来索引数据数组,然后过滤掉NaNs。

filtered_data = data[~np.isnan(data)]

一个完整的例子(改编自here)

对于一维数据:

import matplotlib.pyplot as plt
import numpy as np

# fake up some data
spread = np.random.rand(50) * 100
center = np.ones(25) * 50
flier_high = np.random.rand(10) * 100 + 100
flier_low = np.random.rand(10) * -100
data = np.concatenate((spread, center, flier_high, flier_low), 0)

# Add a NaN
data[40] = np.NaN

# Filter data using np.isnan
filtered_data = data[~np.isnan(data)]

# basic plot
plt.boxplot(filtered_data)

plt.show()

对于二维数据:

对于二维数据,您不能简单地使用上面的掩码,因为这样数据数组的每一列都会有不同的长度。相反,我们可以创建一个列表,列表中的每一项都是数据数组每一列的过滤数据。

列表推导式可以在一行中完成:[d[m] for d, m in zip(data.T, mask.T)]

import matplotlib.pyplot as plt
import numpy as np

# fake up some data
spread = np.random.rand(50) * 100
center = np.ones(25) * 50
flier_high = np.random.rand(10) * 100 + 100
flier_low = np.random.rand(10) * -100
data = np.concatenate((spread, center, flier_high, flier_low), 0)

data = np.column_stack((data, data * 2., data + 20.))

# Add a NaN
data[30, 0] = np.NaN
data[20, 1] = np.NaN

# Filter data using np.isnan
mask = ~np.isnan(data)
filtered_data = [d[m] for d, m in zip(data.T, mask.T)]

# basic plot
plt.boxplot(filtered_data)

plt.show()

我将把它作为练习留给读者,将其扩展到 3 个或更多维度,但你明白了。

【讨论】:

谢谢,它在一维上效果很好,但在二维和三维上就不行了。 (请注意您的数据是 2D,而不是 3D,因为您使用 [:, iD, :] 对数据进行切片) 由于 boxplot 只能显示 1D 和 2D 数据,并且由于 mplot3d 工具包中没有 boxplot 的版本,所以对于读者来说,这个练习可能会导致哪里有点不清楚。 谢谢汤姆。真的很有帮助。 @ImportanceOfBeingErnest,当然,虽然您可能无法以这种方式在 matplotlib 中绘制 3D 箱线图,但您可以设想一种情况,您可能希望以类似的方式过滤 3D 数据,是否然后绘制它或执行一些其他分析。

以上是关于使用python绘制箱线图时如何处理NaN值的主要内容,如果未能解决你的问题,请参考以下文章

可视化实验十二:利用Python绘制箱线图折线图

可视化实验十二:利用Python绘制箱线图折线图

R语言绘制箱线图分面并添加文本注释(基础知识)

Python:获取所有节点的度数,然后在networkx中绘制箱线图

python matplotlib箱线图

python可视化---箱线图boxplot()