Pandas中位数的奇怪行为

17

考虑以下数据框:

       b           c     d     e  f     g     h
0   6.25  2018-04-01  True   NaN  7  54.0  64.0
1  32.50  2018-04-01  True   NaN  7  54.0  64.0
2  16.75  2018-04-01  True   NaN  7  54.0  64.0
3  29.25  2018-04-01  True   NaN  7  54.0  64.0
4  21.75  2018-04-01  True   NaN  7  54.0  64.0
5  21.75  2018-04-01  True  True  7  54.0  64.0
6   7.75  2018-04-01  True  True  7  54.0  64.0
7  23.25  2018-04-01  True  True  7  54.0  64.0
8  12.25  2018-04-01  True  True  7  54.0  64.0
9  30.50  2018-04-01  True   NaN  7  54.0  64.0

(复制并粘贴并使用df = pd.read_clipboard()创建数据框)

最初寻找中位数没有问题:

df.median()

b    21.75
d     1.00
e     1.00
f     7.00
g    54.00
h    64.00
dtype: float64

然而,如果删除了一列,然后找到median,那么列e的中位数会消失:

new_df = df.drop(columns=['b'])
new_df.median()

d     1.0
f     7.0
g    54.0
h    64.0
dtype: float64

这种行为有点出人意料,但仅针对列e查找中位数仍然有效:

new_df['e'].median()
1.0

使用 skipna=False 没有任何区别:

new_df.median(skipna=False)

d     1.0
f     7.0
g    54.0
h    64.0
dtype: float64
它适用于原始数据框:
df.median(skipna=False)

b    21.75
d     1.00
e      NaN
f     7.00
g    54.00
h    64.00
dtype: float64
edfnew_df中的数据类型均为object,两个数据帧之间唯一的区别是new_df没有列b。把列添加回new_df并不能解决这个问题。只有当第一列b被删除时才会出现这个问题。如果列e的数据类型是浮点或整数,则不会发生此情况。

这种行为存在于pandas==0.22.0pandas==0.24.1中。

现在有一个开放的GitHub问题供任何人尝试解决!


1
这很奇怪。当你删除“b”时,第一列似乎存在“非数字”的问题。例如,使用df ['c'] = 1时,删除“b”没有任何问题。 - ALollz
我认为这是一个错误。 - BENY
有趣。如果替换值:df.e=1,则不会发生消失。 - Alex Yu
2
它必须依赖于列的类型。如果我们用 df.c=1df.e=1 替换列 ce - 之后不会发生任何神秘事件。非常有趣。 - Alex Yu
我想这是一个bug。而且这个bug不在于列的消失,而在于对df.e中的object列计算中位数时出现了问题。 - Alex Yu
我通过复制/粘贴new_df,使用new_df = pd.read_clipboard()进行了复制。我得到的结果与new_df = df.drop(columns=['b'])完全相同。我猜测是数据结构引起了错误(我怀疑是复制/查看问题)。GitHub上已经有问题了吗? - Adrien Pacifico
1个回答

3
这似乎是一个bug。当我们将任何df分派到median时,这将映射到内部的_reduce函数。当numeric_only设置为None时,它通过系列计算中位数,并忽略失败(例如,对于c列,中位数计算将失败),并累积结果(请参见pandas源代码core/frame.py中的_reduce)。到目前为止都很好。但是,在通过它将结果拼接在一起时,它会进行检查以推断结果是标量还是系列(对于中位数,它当然是标量)。为了进行此检查,它总是使用第一列(请参见pandas源代码core/apply.py中的wrap_results)。因此,如果第一列的计算失败并被跳过,则此检查将失败,引发异常。这将触发_reduce中的后备方法,强制数据框仅为数字(删除任何带有NaN的列)并重新计算中位数。
因此,在您的情况下,如果列c(或任何其他中位数计算将失败的dtype,如文本)在第一列中,则所有带有NaN的列也将被删除以得出中位数结果。设置skipna不会改变,因为bug出在非数字列在第一位置上触发强制数字计算。我认为没有任何修复可能,除非在pandas代码库中进行修复,或确保第一列始终成功进行中位数计算。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接