堆叠pandas DataFrame时设置列名

时间:2015-10-07 17:37:03

标签: python pandas

堆叠大熊猫DataFrame时,会返回Series。通常在我堆叠DataFrame后,我将其转换回DataFrame。但是,来自堆叠数据的默认名称使列重命名有点hacky。我正在寻找的是一种更简单/内置的方法,可以在堆叠后为列提供合理的名称。

例如,对于以下DataFrame

In [64]: df = pd.DataFrame({'id':[1,2,3], 
    ...:                    'date':['2015-09-31']*3, 
    ...:                    'value':[100, 95, 42], 
    ...:                    'value2':[200, 57, 27]}).set_index(['id','date'])

In [65]: df
Out[65]: 
               value  value2
id date                     
1  2015-09-31    100     200
2  2015-09-31     95      57
3  2015-09-31     42      27

我将它堆叠并转换回DataFrame,如下所示:

In [68]: df.stack().reset_index()
Out[68]: 
   id        date level_2    0
0   1  2015-09-31   value  100
1   1  2015-09-31  value2  200
2   2  2015-09-31   value   95
3   2  2015-09-31  value2   57
4   3  2015-09-31   value   42
5   3  2015-09-31  value2   27

因此,为了恰当地命名这些列,我需要做这样的事情:

In [72]: stacked = df.stack()

In [73]: stacked
Out[73]: 
id  date              
1   2015-09-31  value     100
                value2    200
2   2015-09-31  value      95
                value2     57
3   2015-09-31  value      42
                value2     27
dtype: int64

In [74]: stacked.index.set_names('var_name', level=len(stacked.index.names)-1, inplace=True)

In [88]: stacked.reset_index().rename(columns={0:'value'})
Out[88]: 
   id        date var_name  value
0   1  2015-09-31    value    100
1   1  2015-09-31   value2    200
2   2  2015-09-31    value     95
3   2  2015-09-31   value2     57
4   3  2015-09-31    value     42
5   3  2015-09-31   value2     27

理想情况下,解决方案看起来像这样:

df.stack(new_index_name='var_name', new_col_name='value')

但是看docs stack它看起来不像CMP。在熊猫中有更简单/内置的方式来处理这个工作流程吗?

4 个答案:

答案 0 :(得分:11)

所以,在columnsSeries也可以带名字的情况下,您可以找到更清洁的一种方式。

In [45]: df
Out[45]: 
               value  value2
id date                     
1  2015-09-31    100     200
2  2015-09-31     95      57
3  2015-09-31     42      27

In [46]: df.columns.name = 'var_name'

In [47]: s = df.stack()

In [48]: s.name = 'value'

In [49]: s.reset_index()
Out[49]: 
   id        date var_name  value
0   1  2015-09-31    value    100
1   1  2015-09-31   value2    200
2   2  2015-09-31    value     95
3   2  2015-09-31   value2     57
4   3  2015-09-31    value     42
5   3  2015-09-31   value2     27

答案 1 :(得分:11)

pd.melt通常可用于转换来自"宽"的数据框架。到"长"格式。如果您首先将pd.meltid索引级别转换为列,则可以在此使用date

In [56]: pd.melt(df.reset_index(), id_vars=['id', 'date'], value_vars=['value', 'value2'], var_name='var_name', value_name='value')
Out[56]: 
   id        date var_name  value
0   1  2015-09-31    value    100
1   2  2015-09-31    value     95
2   3  2015-09-31    value     42
3   1  2015-09-31   value2    200
4   2  2015-09-31   value2     57
5   3  2015-09-31   value2     27

答案 2 :(得分:2)

克里斯宾答案的管道友好替代方法:

 jdbcTemplate.execute(new PreparedStatementCreator() {
        @Override
        public PreparedStatement createPreparedStatement(Connection connection)

                throws SQLException, DataAccessException {

            PreparedStatement ps = connection.prepareStatement("select dcr_number from dcr_mols WHERE flexmatch(ctab,?,'MATCH=ALL')=1");
            Clob myClob =  connection.createClob();
            myClob.setString( 1, fileDataStr);
            MapSqlParameterSource parameters = new MapSqlParameterSource();
            parameters.addValue("file_data", myClob, Types.CLOB);
            ps.setClob(1,myClob);
            return ps;

        };
    }, new MyPreparedStatementCallback());

如果显式优于隐式:

df.stack().rename_axis(['id', 'date', 'var_name']).rename('value').reset_index()

使用字典映射器时,您可以跳过应保持相同的名称:

(
    df
    .stack()
    .rename_axis(index={'id': 'id', 'date': 'date', None: 'var_name'})
    .rename('value')
    .reset_index()
)

答案 3 :(得分:0)

为什么不是这样的? 有时melt很棒, 但有时你想保留你的索引, 和/或您想在该新列上建立索引。 这就像@krassowski 的回答, 但它不需要您提前知道 df 的索引名称。

df.stack().rename_axis([*df.index.names, "var_name"]).rename("value")