Python pandas:如果任何列值为 NaN,我如何删除分层索引中的特定级别?
Python pandas: How do I drop specific levels in a hierarchical index if any column values are 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)
来尝试使国家/地区的删除更容易,但这两种方法都是为了将水平保留在DataFrame 如果 M1 和 M2 包含值,例如2010 年的孟加拉国。
有什么简洁的方法可以解决这个问题吗?
此代码块底部的三行代码完成了繁重的工作,其余部分将您的数据放入 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
是的,有一种简洁有效的方法可以解决这个问题。 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
使 "Year" 成为最里面的列标签
>>> 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()
如果某个国家/地区的任何数据值为 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)
来尝试使国家/地区的删除更容易,但这两种方法都是为了将水平保留在DataFrame 如果 M1 和 M2 包含值,例如2010 年的孟加拉国。
有什么简洁的方法可以解决这个问题吗?
此代码块底部的三行代码完成了繁重的工作,其余部分将您的数据放入 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
是的,有一种简洁有效的方法可以解决这个问题。 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
使 "Year" 成为最里面的列标签
>>> 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()