Python pandas:如果任何列值为NaN,如何删除层次索引中的特定级别?

时间:2015-04-18 02:27:36

标签: python pandas dataframe nan

如果该国家/地区的任何数据值都是NaN,我想在我的分层索引中删除整个级别(在本例中为国家/地区)。所以我想从这样的事情出发:

                          M1                   M2
country    year                                   
Arab World 2010           5.240002             NaN
           2009           NaN                  NaN
Bangladesh 2010           6.206065             3.7
           2009           5.708707             NaN
Canada     2010           7.203803             5.8
           2009           6.144833             7.0
Sweden     2010           9.123140             6.0
           2009           5.213283             6.1

这样的事情:

                          M1                   M2
country    year                                   
Canada     2010           7.203803             5.8
           2009           6.144833             7.0
Sweden     2010           9.123140             6.0
           2009           5.213283             6.1

我已尝试df.dropna()使用thresh选项,以及df.fillna(0)尝试更轻松地删除国家/地区,但这两种方法都是为了让如果M1和M2包含值,则为DataFrame,例如孟加拉国在2010年。

有没有简洁的方法来解决这个问题?

2 个答案:

答案 0 :(得分:2)

此代码块底部的三行执行繁重的工作,其余的将数据放入DataFrame(或多或少)。

# get data
data="""
country    year           M1                   M2 
Arab_World 2010           5.240002             NaN
Arab_World 2009           NaN                  NaN
Bangladesh 2010           6.206065             3.7
Bangladesh 2009           5.708707             NaN
Canada     2010           7.203803             5.8
Canada     2009           6.144833             7.0
Sweden     2010           9.123140             6.0
Sweden     2009           5.213283             6.1"""
from StringIO import StringIO # import from io for python 3
df = pd.read_csv(StringIO(data), header=0, index_col=['country', 'year'], sep=r'\s+')

# manipulate rows
to_drop = df.groupby(level='country').apply(lambda x: x.isnull().any().any())
df = df.reset_index(level=0)
keepers = df[(~to_drop[df.country]).tolist()]

产量

In [13]: print(keepers)
     country        M1   M2
year                       
2010  Canada  7.203803  5.8
2009  Canada  6.144833  7.0
2010  Sweden  9.123140  6.0
2009  Sweden  5.213283  6.1

答案 1 :(得分:2)

是的,有一种简洁有效的方法可以解决这个问题。您使用df.dropna()走在正确的轨道上,只需要在申请之前unstack数据。

>>> print df

                       M1   M2
Country    Year               
Arab World 2009       NaN  NaN
           2010  5.240002  NaN
Bangladesh 2009  5.708707  NaN
           2010  6.206065  3.7
Canada     2009  6.144833  7.0
           2010  7.203803  5.8
Sweden     2009  5.213283  6.1
           2010  9.123140  6.0

转动DataFrame以制作"年"最里面的列标签

>>> df1 = df.unstack(level=-1)

删除缺少数据的行

>>> df2 = df1.dropna()  

撤销拆散

>>> print df2.stack()

                    M1   M2
Country Year               
Canada  2009  6.144833  7.0
        2010  7.203803  5.8
Sweden  2009  5.213283  6.1
        2010  9.123140  6.0

把所有这些放在一起:

>>> clean = df.unstack(level=-1).dropna().stack()