堆叠大熊猫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
。在熊猫中有更简单/内置的方式来处理这个工作流程吗?
答案 0 :(得分:11)
所以,在columns
和Series
也可以带名字的情况下,您可以找到更清洁的一种方式。
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.melt
和id
索引级别转换为列,则可以在此使用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")