Python Pandas crosstab()函数与包含NaN值的数据帧的混淆行为

Python Pandas crosstab()函数与包含NaN值的数据帧的混淆行为,python,pandas,dataframe,nan,crosstab,Python,Pandas,Dataframe,Nan,Crosstab,我正在将Python 3.4.1与numpy 0.10.1和pandas 0.17.0一起使用。我有一个大的数据框,列出了个体动物的物种和性别。这是一个真实的数据集,不可避免地会缺少由NaN表示的值。数据的简化版本可以生成为: import numpy as np import pandas as pd tempDF = pd.DataFrame({ 'id': [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],

我正在将Python 3.4.1与numpy 0.10.1和pandas 0.17.0一起使用。我有一个大的数据框,列出了个体动物的物种和性别。这是一个真实的数据集,不可避免地会缺少由NaN表示的值。数据的简化版本可以生成为:

import numpy as np
import pandas as pd
tempDF = pd.DataFrame({ 'id': [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
                        'species': ["dog","dog",np.nan,"dog","dog","cat","cat","cat","dog","cat","cat","dog","dog","dog","dog",np.nan,"cat","cat","dog","dog"],
                        'gender': ["male","female","female","male","male","female","female",np.nan,"male","male","female","male","female","female","male","female","male","female",np.nan,"male"]})
打印数据框将提供:

    gender  id species
0     male   1     dog
1   female   2     dog
2   female   3     NaN
3     male   4     dog
4     male   5     dog
5   female   6     cat
6   female   7     cat
7      NaN   8     cat
8     male   9     dog
9     male  10     cat
10  female  11     cat
11    male  12     dog
12  female  13     dog
13  female  14     dog
14    male  15     dog
15  female  16     NaN
16    male  17     cat
17  female  18     cat
18     NaN  19     dog
19    male  20     dog
我想生成一个交叉表,用以下公式显示每个物种的雄性和雌性数量:

pd.crosstab(tempDF['species'],tempDF['gender'])
这将生成下表:

gender   female  male
species              
cat           4     2
dog           3     7
这正是我所期望的。但是,如果我包括margins=True选项,它将生成:

pd.crosstab(tempDF['species'],tempDF['gender'],margins=True)

gender   female  male  All
species                   
cat           4     2    7
dog           3     7   11
All           9     9   20
如您所见,边际总计似乎不正确,可能是由于数据帧中缺少数据造成的。这是故意的行为吗?在我看来,这似乎很令人困惑。当然,边际总计应该是表中显示的行和列的总计,不包括表中未显示的任何缺失数据。包括dropna=False并不影响结果


在创建表之前,我可以删除任何带有NaN的行,但在进行分析时,这似乎是一项额外的工作,需要考虑很多额外的事情。我是否应该将此报告为错误?

我认为一种解决方法是在创建表格之前将NAN转换为“缺失”,然后交叉管道将包括专门针对缺失值的列和行:

pd.crosstab(tempDF['species'].fillna('missing'),tempDF['gender'].fillna('missing'),margins=True)

gender   female  male  missing  All
species                            
cat           4     2        1    7
dog           3     7        1   11
missing       2     0        0    2
All           9     9        2   20

就个人而言,我希望看到默认行为,这样我就不必记得在每次交叉表计算中替换所有的NAN。

您不是唯一一个遇到这种情况的人。 这不仅发生在pd.crosstab上,还发生在pd.pivot_table和DataFrame.groupby上

在文档中,它对groupby(不包括Na)这样说:

GroupBy中的NA组将自动排除。这种行为是错误的 例如,与R一致

你可以在这篇文章中找到一些好的解决方案:


也许有一天有人会解决这个问题:

也许用df.dropna()创建第二个数据帧,然后在这个新的数据帧上调用交叉表?我同意这是一个选项,但它给一个非常简单的过程增加了一层复杂性。而且(如果数据帧中有许多其他变量,每个变量都带有NAN),这可能意味着为您想要生成的每个交叉表生成许多新的数据帧。