Python pandas DataFrame.stack(dropna=False),但保留现有的级别组合

Python pandas DataFrame.stack(dropna=False),但保留现有的级别组合,python,python-3.x,pandas,Python,Python 3.x,Pandas,我的数据是这样的 import numpy as np import pandas as pd # My Data enroll_year = np.arange(2010, 2015) grad_year = enroll_year + 4 n_students = [[100, 100, 110, 110, np.nan]] df = pd.DataFrame( n_students, columns=pd.MultiIndex.from_arrays(

我的数据是这样的

import numpy as np
import pandas as pd

# My Data
enroll_year = np.arange(2010, 2015)
grad_year = enroll_year + 4
n_students = [[100, 100, 110, 110, np.nan]]

df = pd.DataFrame(
    n_students, 
    columns=pd.MultiIndex.from_arrays(
        [enroll_year, grad_year], 
        names=['enroll_year', 'grad_year']))

print(df)
# enroll_year 2010 2011 2012 2013 2014
# grad_year   2014 2015 2016 2017 2018
# 0            100  100  110  110  NaN
我想做的是叠加数据,一个列/索引级别表示入学年份,一个列/索引级别表示毕业年份,一个列/索引级别表示学生人数,如下所示

# enroll_year  grad_year    n
# 2010         2014         100.0
# .            .                .
# .            .                .
# .            .                .
# 2014         2018           NaN
.stack()
生成的数据非常接近,但丢失的记录被删除

df1 = df.stack(['enroll_year', 'grad_year'])
df1.index = df1.index.droplevel(0)
print(df1)
# enroll_year  grad_year
# 2010         2014         100.0
# 2011         2015         100.0
# 2012         2016         110.0
# 2013         2017         110.0
# dtype: float64
因此,尝试了
.stack(dropna=False)
,但它会将索引级别扩展到入学和毕业年份的所有组合

df2 = df.stack(['enroll_year', 'grad_year'], dropna=False)
df2.index = df2.index.droplevel(0)
print(df2)
# enroll_year  grad_year
# 2010         2014         100.0
#              2015           NaN
#              2016           NaN
#              2017           NaN
#              2018           NaN
# 2011         2014           NaN
#              2015         100.0
#              2016           NaN
#              2017           NaN
#              2018           NaN
# 2012         2014           NaN
#              2015           NaN
#              2016         110.0
#              2017           NaN
#              2018           NaN
# 2013         2014           NaN
#              2015           NaN
#              2016           NaN
#              2017         110.0
#              2018           NaN
# 2014         2014           NaN
#              2015           NaN
#              2016           NaN
#              2017           NaN
#              2018           NaN
# dtype: float64
我需要子集
df2
,以获得所需的数据集

existing_combn = list(zip(
    df.columns.levels[0][df.columns.labels[0]], 
    df.columns.levels[1][df.columns.labels[1]]))

df3 = df2.loc[existing_combn]
print(df3)
# enroll_year  grad_year
# 2010         2014         100.0
# 2011         2015         100.0
# 2012         2016         110.0
# 2013         2017         110.0
# 2014         2018           NaN
# dtype: float64
虽然它只在我的代码中增加了几行额外的内容,但我想知道是否有更好更整洁的方法。

pd.DataFrame
一起使用,然后
reset\u index
drop
不必要的列和
将列重命名为:

pd.DataFrame(df.unstack()).reset_index().drop('level_2',axis=1).rename(columns={0:'n'})

   enroll_year  grad_year      n
0         2010       2014  100.0
1         2011       2015  100.0
2         2012       2016  110.0
3         2013       2017  110.0
4         2014       2018    NaN
或:

或:


说明:

print(pd.DataFrame(df.unstack()))
                             0
enroll_year grad_year         
2010        2014      0  100.0
2011        2015      0  100.0
2012        2016      0  110.0
2013        2017      0  110.0
2014        2018      0    NaN

print(pd.DataFrame(df.unstack()).reset_index().drop('level_2',axis=1))
   enroll_year  grad_year      0
0         2010       2014  100.0
1         2011       2015  100.0
2         2012       2016  110.0
3         2013       2017  110.0
4         2014       2018    NaN

print(pd.DataFrame(df.unstack()).reset_index().drop('level_2',axis=1).rename(columns={0:'n'}))
   enroll_year  grad_year      n
0         2010       2014  100.0
1         2011       2015  100.0
2         2012       2016  110.0
3         2013       2017  110.0
4         2014       2018    NaN
pd.DataFrame
一起使用,然后
reset\u index
drop
不必要的列,并
将列重命名为:

pd.DataFrame(df.unstack()).reset_index().drop('level_2',axis=1).rename(columns={0:'n'})

   enroll_year  grad_year      n
0         2010       2014  100.0
1         2011       2015  100.0
2         2012       2016  110.0
3         2013       2017  110.0
4         2014       2018    NaN
或:

或:


说明:

print(pd.DataFrame(df.unstack()))
                             0
enroll_year grad_year         
2010        2014      0  100.0
2011        2015      0  100.0
2012        2016      0  110.0
2013        2017      0  110.0
2014        2018      0    NaN

print(pd.DataFrame(df.unstack()).reset_index().drop('level_2',axis=1))
   enroll_year  grad_year      0
0         2010       2014  100.0
1         2011       2015  100.0
2         2012       2016  110.0
3         2013       2017  110.0
4         2014       2018    NaN

print(pd.DataFrame(df.unstack()).reset_index().drop('level_2',axis=1).rename(columns={0:'n'}))
   enroll_year  grad_year      n
0         2010       2014  100.0
1         2011       2015  100.0
2         2012       2016  110.0
3         2013       2017  110.0
4         2014       2018    NaN