Ros*_*s R 266 python dataframe pandas
我有一个数据框,在第1轴(列)中有一个分层索引(来自一个groupby.agg
操作):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf
sum sum sum sum amax amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
Run Code Online (Sandbox Code Playgroud)
我想扁平它,所以它看起来像这样(名字不重要 - 我可以重命名):
USAF WBAN year month day s_PC s_CL s_CD s_CNT tempf_amax tmpf_amin
0 702730 26451 1993 1 1 1 0 12 13 30.92 24.98
1 702730 26451 1993 1 2 0 0 13 13 32.00 24.98
2 702730 26451 1993 1 3 1 10 2 13 23.00 6.98
3 702730 26451 1993 1 4 1 0 12 13 10.04 3.92
4 702730 26451 1993 1 5 3 0 10 13 19.94 10.94
Run Code Online (Sandbox Code Playgroud)
我该怎么做呢?(我已经尝试了很多,但无济于事.)
根据一个建议,这里是dict形式的头
{('USAF', ''): {0: '702730',
1: '702730',
2: '702730',
3: '702730',
4: '702730'},
('WBAN', ''): {0: '26451', 1: '26451', 2: '26451', 3: '26451', 4: '26451'},
('day', ''): {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
('month', ''): {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
('s_CD', 'sum'): {0: 12.0, 1: 13.0, 2: 2.0, 3: 12.0, 4: 10.0},
('s_CL', 'sum'): {0: 0.0, 1: 0.0, 2: 10.0, 3: 0.0, 4: 0.0},
('s_CNT', 'sum'): {0: 13.0, 1: 13.0, 2: 13.0, 3: 13.0, 4: 13.0},
('s_PC', 'sum'): {0: 1.0, 1: 0.0, 2: 1.0, 3: 1.0, 4: 3.0},
('tempf', 'amax'): {0: 30.920000000000002,
1: 32.0,
2: 23.0,
3: 10.039999999999999,
4: 19.939999999999998},
('tempf', 'amin'): {0: 24.98,
1: 24.98,
2: 6.9799999999999969,
3: 3.9199999999999982,
4: 10.940000000000001},
('year', ''): {0: 1993, 1: 1993, 2: 1993, 3: 1993, 4: 1993}}
Run Code Online (Sandbox Code Playgroud)
And*_*den 391
我认为最简单的方法是将列设置为顶级:
df.columns = df.columns.get_level_values(0)
Run Code Online (Sandbox Code Playgroud)
注意:如果to级别有名称,您也可以通过此访问它,而不是0.
.
如果你想将join
你的MultiIndex 组合成一个索引(假设你的列中只有字符串条目),你可以:
df.columns = [' '.join(col).strip() for col in df.columns.values]
Run Code Online (Sandbox Code Playgroud)
注意:strip
当没有第二个索引时,我们必须有空格.
In [11]: [' '.join(col).strip() for col in df.columns.values]
Out[11]:
['USAF',
'WBAN',
'day',
'month',
's_CD sum',
's_CL sum',
's_CNT sum',
's_PC sum',
'tempf amax',
'tempf amin',
'year']
Run Code Online (Sandbox Code Playgroud)
小智 75
pd.DataFrame(df.to_records()) # multiindex become columns and new index is integers only
Run Code Online (Sandbox Code Playgroud)
The*_*eke 38
Andy Hayden的回答肯定是最简单的方法 - 如果你想避免重复的列标签,你需要调整一下
In [34]: df
Out[34]:
USAF WBAN day month s_CD s_CL s_CNT s_PC tempf year
sum sum sum sum amax amin
0 702730 26451 1 1 12 0 13 1 30.92 24.98 1993
1 702730 26451 2 1 13 0 13 0 32.00 24.98 1993
2 702730 26451 3 1 2 10 13 1 23.00 6.98 1993
3 702730 26451 4 1 12 0 13 1 10.04 3.92 1993
4 702730 26451 5 1 10 0 13 3 19.94 10.94 1993
In [35]: mi = df.columns
In [36]: mi
Out[36]:
MultiIndex
[(USAF, ), (WBAN, ), (day, ), (month, ), (s_CD, sum), (s_CL, sum), (s_CNT, sum), (s_PC, sum), (tempf, amax), (tempf, amin), (year, )]
In [37]: mi.tolist()
Out[37]:
[('USAF', ''),
('WBAN', ''),
('day', ''),
('month', ''),
('s_CD', 'sum'),
('s_CL', 'sum'),
('s_CNT', 'sum'),
('s_PC', 'sum'),
('tempf', 'amax'),
('tempf', 'amin'),
('year', '')]
In [38]: ind = pd.Index([e[0] + e[1] for e in mi.tolist()])
In [39]: ind
Out[39]: Index([USAF, WBAN, day, month, s_CDsum, s_CLsum, s_CNTsum, s_PCsum, tempfamax, tempfamin, year], dtype=object)
In [40]: df.columns = ind
In [46]: df
Out[46]:
USAF WBAN day month s_CDsum s_CLsum s_CNTsum s_PCsum tempfamax tempfamin \
0 702730 26451 1 1 12 0 13 1 30.92 24.98
1 702730 26451 2 1 13 0 13 0 32.00 24.98
2 702730 26451 3 1 2 10 13 1 23.00 6.98
3 702730 26451 4 1 12 0 13 1 10.04 3.92
4 702730 26451 5 1 10 0 13 3 19.94 10.94
year
0 1993
1 1993
2 1993
3 1993
4 1993
Run Code Online (Sandbox Code Playgroud)
onl*_*tom 29
该线程上的所有当前答案都必须已过时。从pandas
0.24.0版开始,.to_flat_index()
您需要做什么。
从熊猫自己的文档中:
MultiIndex.to_flat_index()
将MultiIndex转换为包含级别值的元组索引。
文档中的一个简单示例:
import pandas as pd
print(pd.__version__) # '0.23.4'
index = pd.MultiIndex.from_product(
[['foo', 'bar'], ['baz', 'qux']],
names=['a', 'b'])
print(index)
# MultiIndex(levels=[['bar', 'foo'], ['baz', 'qux']],
# codes=[[1, 1, 0, 0], [0, 1, 0, 1]],
# names=['a', 'b'])
Run Code Online (Sandbox Code Playgroud)
申请to_flat_index()
:
index.to_flat_index()
# Index([('foo', 'baz'), ('foo', 'qux'), ('bar', 'baz'), ('bar', 'qux')], dtype='object')
Run Code Online (Sandbox Code Playgroud)
pandas
列一个如何在上使用它的示例dat
,它是一个带有MultiIndex
列的DataFrame :
dat = df.loc[:,['name','workshop_period','class_size']].groupby(['name','workshop_period']).describe()
print(dat.columns)
# MultiIndex(levels=[['class_size'], ['count', 'mean', 'std', 'min', '25%', '50%', '75%', 'max']],
# codes=[[0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 2, 3, 4, 5, 6, 7]])
dat.columns = dat.columns.to_flat_index()
print(dat.columns)
# Index([('class_size', 'count'), ('class_size', 'mean'),
# ('class_size', 'std'), ('class_size', 'min'),
# ('class_size', '25%'), ('class_size', '50%'),
# ('class_size', '75%'), ('class_size', 'max')],
# dtype='object')
Run Code Online (Sandbox Code Playgroud)
bod*_*y11 16
对我来说,最简单、最直观的解决方案是使用get_level_values组合列名。这可以防止在同一列上进行多个聚合时出现重复的列名:
level_one = df.columns.get_level_values(0).astype(str)
level_two = df.columns.get_level_values(1).astype(str)
df.columns = level_one + level_two
Run Code Online (Sandbox Code Playgroud)
如果您想在列之间使用分隔符,您可以这样做。这将返回与 Seiji Armstrong 对已接受答案的评论相同的内容,该答案仅包含具有两个索引级别值的列的下划线:
level_one = df.columns.get_level_values(0).astype(str)
level_two = df.columns.get_level_values(1).astype(str)
column_separator = ['_' if x != '' else '' for x in level_two]
df.columns = level_one + column_separator + level_two
Run Code Online (Sandbox Code Playgroud)
我知道这与上面安迪·海登 (Andy Hayden) 的出色回答具有相同的作用,但我认为这种方式更直观,更容易记住(因此我不必继续参考此线程),尤其是对于熊猫新手用户.
在您可能有 3 个列级别的情况下,此方法也更具可扩展性。
level_one = df.columns.get_level_values(0).astype(str)
level_two = df.columns.get_level_values(1).astype(str)
level_three = df.columns.get_level_values(2).astype(str)
df.columns = level_one + level_two + level_three
Run Code Online (Sandbox Code Playgroud)
tvt*_*173 15
df.columns = ['_'.join(tup).rstrip('_') for tup in df.columns.values]
Run Code Online (Sandbox Code Playgroud)
Zel*_*ny7 13
如果你想保留多索引第二级的任何聚合信息,你可以试试这个:
In [1]: new_cols = [''.join(t) for t in df.columns]
Out[1]:
['USAF',
'WBAN',
'day',
'month',
's_CDsum',
's_CLsum',
's_CNTsum',
's_PCsum',
'tempfamax',
'tempfamin',
'year']
In [2]: df.columns = new_cols
Run Code Online (Sandbox Code Playgroud)
使用map
函数的最pythonic方法。
df.columns = df.columns.map(' '.join).str.strip()
Run Code Online (Sandbox Code Playgroud)
输出print(df.columns)
:
Index(['USAF', 'WBAN', 'day', 'month', 's_CD sum', 's_CL sum', 's_CNT sum',
's_PC sum', 'tempf amax', 'tempf amin', 'year'],
dtype='object')
Run Code Online (Sandbox Code Playgroud)
df.columns = [f'{f} {s}' if s != '' else f'{f}'
for f, s in df.columns]
print(df.columns)
Run Code Online (Sandbox Code Playgroud)
输出:
Index(['USAF', 'WBAN', 'day', 'month', 's_CD sum', 's_CL sum', 's_CNT sum',
's_PC sum', 'tempf amax', 'tempf amin', 'year'],
dtype='object')
Run Code Online (Sandbox Code Playgroud)
处理多个级别和混合类型的常规解决方案:
df.columns = ['_'.join(tuple(map(str, t))) for t in df.columns.values]
Run Code Online (Sandbox Code Playgroud)
阅读完所有答案后,我想到了:
def __my_flatten_cols(self, how="_".join, reset_index=True):
how = (lambda iter: list(iter)[-1]) if how == "last" else how
self.columns = [how(filter(None, map(str, levels))) for levels in self.columns.values] \
if isinstance(self.columns, pd.MultiIndex) else self.columns
return self.reset_index() if reset_index else self
pd.DataFrame.my_flatten_cols = __my_flatten_cols
Run Code Online (Sandbox Code Playgroud)
给定一个数据框:
df = pd.DataFrame({"grouper": ["x","x","y","y"], "val1": [0,2,4,6], 2: [1,3,5,7]}, columns=["grouper", "val1", 2])
grouper val1 2
0 x 0 1
1 x 2 3
2 y 4 5
3 y 6 7
Run Code Online (Sandbox Code Playgroud)
单一聚合方法:与源名称相同的结果变量:
df.groupby(by="grouper").agg("min").my_flatten_cols()
Run Code Online (Sandbox Code Playgroud)
df.groupby(by="grouper",
as_index = False)
或.agg(...)
.reset_index()相同----- before -----
val1 2
grouper
------ after -----
grouper val1 2
0 x 0 1
1 y 4 5
Run Code Online (Sandbox Code Playgroud)单源变量,多个聚合:以统计信息命名的结果变量:
df.groupby(by="grouper").agg({"val1": [min,max]}).my_flatten_cols("last")
Run Code Online (Sandbox Code Playgroud)
a = df.groupby(..).agg(..); a.columns = a.columns.droplevel(0); a.reset_index()
。----- before -----
val1
min max
grouper
------ after -----
grouper min max
0 x 0 2
1 y 4 6
Run Code Online (Sandbox Code Playgroud)多个变量,多个聚合:名为(varname)_(statname)的结果变量:
df.groupby(by="grouper").agg({"val1": min, 2:[sum, "size"]}).my_flatten_cols()
# you can combine the names in other ways too, e.g. use a different delimiter:
#df.groupby(by="grouper").agg({"val1": min, 2:[sum, "size"]}).my_flatten_cols(" ".join)
Run Code Online (Sandbox Code Playgroud)
a.columns = ["_".join(filter(None, map(str, levels))) for levels in a.columns.values]
(因为这种形式的agg()
结果出现MultiIndex
在列中)。my_flatten_cols
助手,则键入@Seigi:建议的解决方案可能会更容易,a.columns = ["_".join(t).rstrip("_") for t in a.columns.values]
在这种情况下,它的工作原理类似(但如果列上有数字标签,则会失败)a.columns = ["_".join(tuple(map(str, t))).rstrip("_") for t in a.columns.values]
)建议的解决方案,但是我不明白为什么tuple()
需要调用,并且我相信rstrip()
只有在某些列具有类似("colname", "")
(如果您reset_index()
在尝试修复之前会发生这种情况.columns
)----- before -----
val1 2
min sum size
grouper
------ after -----
grouper val1_min 2_sum 2_size
0 x 0 4 2
1 y 4 12 2
Run Code Online (Sandbox Code Playgroud)要手动命名结果变量:(这是因为大熊猫0.20.0弃用与没有适当的替代性为0.23)
df.groupby(by="grouper").agg({"val1": {"sum_of_val1": "sum", "count_of_val1": "count"},
2: {"sum_of_2": "sum", "count_of_2": "count"}}).my_flatten_cols("last")
Run Code Online (Sandbox Code Playgroud)
res.columns = ['A_sum', 'B_sum', 'count']
或.join()
输入多个groupby
语句。----- before -----
val1 2
count_of_val1 sum_of_val1 count_of_2 sum_of_2
grouper
------ after -----
grouper count_of_val1 sum_of_val1 count_of_2 sum_of_2
0 x 2 2 2 4
1 y 2 10 2 12
Run Code Online (Sandbox Code Playgroud)map(str, ..)
filter(None, ..)
columns.values
返回名称(str
,不是元组).agg()
您可能需要保留一列的最底部标签或连接多个标签reset_index()
能够以常规方式使用“分组依据”列,因此默认情况下会这样做另一个简短的,仅使用熊猫方法:
df.columns = df.columns.to_flat_index().str.join('_')
Run Code Online (Sandbox Code Playgroud)
产量作为输出:
USAF_ WBAN_ day_ month_ ... s_PC_sum tempf_amax tempf_amin year_
0 702730 26451 1 1 ... 1.0 30.92 24.98 1993
1 702730 26451 2 1 ... 0.0 32.00 24.98 1993
2 702730 26451 3 1 ... 1.0 23.00 6.98 1993
3 702730 26451 4 1 ... 1.0 10.04 3.92 1993
4 702730 26451 5 1 ... 3.0 19.94 10.94 1993
Run Code Online (Sandbox Code Playgroud)
您会注意到不属于 MultiIndex 的列的尾随下划线。你提到你不关心名字,所以这可能对你有用。在我自己的类似用例中,所有列都有两个级别,因此这个简单的命令创建了不错的名称。
归档时间: |
|
查看次数: |
167466 次 |
最近记录: |