提问人:piRSquared 提问时间:4/3/2018 最后编辑:Anton ProtopopovpiRSquared 更新时间:12/27/2019 访问量:30636
Pandas 的 concat 函数中的“levels”、“keys”和 names 参数是什么?
What are the 'levels', 'keys', and names arguments for in Pandas' concat function?
问:
问题
- 我该如何使用?
pd.concat
- 论据是什么?
levels
- 论据是什么?
keys
- 有没有一堆例子来帮助解释如何使用所有参数?
Pandas 的功能是合并实用程序的瑞士军刀。它有用的各种情况很多。现有文档遗漏了一些可选参数的细节。其中包括 和 参数。我开始弄清楚这些论点的作用。concat
levels
keys
我将提出一个问题,该问题将作为进入 .pd.concat
考虑数据框 、 和 :d1
d2
d3
import pandas as pd
d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), [2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), [1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), [1, 3])
如果我要将它们与
pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'])
我得到了预期的结果,我的对象有一个:pandas.MultiIndex
columns
A B C D
d1 2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
d2 1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
d3 1 0.7 0.8 NaN 0.9
3 0.7 0.8 NaN 0.9
但是,我想使用levels
参数文档:
levels:序列列表,默认为“无”。 用于构造 MultiIndex 的特定级别(唯一值)。否则,将从密钥推断出它们。
所以我通过了
pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2']])
并获得一个KeyError
ValueError: Key d3 not in level Index(['d1', 'd2'], dtype='object')
这是有道理的。我通过的级别不足以描述按键指示的必要级别。如果我没有像上面那样通过任何东西,就会推断出级别(如文档中所述)。但是,我还能如何使用这个论点来获得更好的效果呢?
如果我尝试过这个:
pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2', 'd3']])
我得到了与上述相同的结果。但是当我在关卡中再添加一个值时,
df = pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2', 'd3', 'd4']])
我最终得到了外观相同的数据框,但结果具有未使用的级别。MultiIndex
df.index.levels[0]
Index(['d1', 'd2', 'd3', 'd4'], dtype='object')
那么这个论点的意义何在,我应该以不同的方式使用吗?level
keys
我正在使用 Python 3.6 和 Pandas 0.22。
答:
在自己回答这个问题的过程中,我学到了很多东西,我想把例子和一些解释放在一起。
争论点的具体答案将在最后出现。levels
pandas.concat
:缺失的手册
导入和定义对象
import pandas as pd
d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), index=[2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), index=[1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), index=[1, 3])
s1 = pd.Series([1, 2], index=[2, 3])
s2 = pd.Series([3, 4], index=[1, 2])
s3 = pd.Series([5, 6], index=[1, 3])
参数
objs
我们遇到的第一个论点是 objs
:
objs:Series、DataFrame 或 Panel 对象的序列或映射 如果传递了字典,则排序后的键将用作键参数,除非传递,在这种情况下,将选择值(见下文)。任何 None 对象都将以静默方式删除,除非它们都是 None,在这种情况下,将引发 ValueError
- 我们通常看到它与 or 对象列表一起使用。
Series
DataFrame
- 我将证明这也非常有用。
dict
- 也可以使用生成器,并且在使用
map
map(f, list_of_df)
现在,我们将坚持使用上面定义的一些 AND 对象的列表。
稍后我将展示如何利用字典来提供非常有用的结果。DataFrame
Series
MultiIndex
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
axis
我们遇到的第二个参数是 axis
,其默认值为 :0
轴:{0/'index', 1/'columns'},默认 0 要连接的轴。
两个s与(堆叠)DataFrame
axis=0
对于 或 的值,我们的意思是说:“沿列对齐并添加到索引中”。0
index
如上所示,我们使用了 ,因为是默认值,我们看到 的索引扩展了 的索引,尽管该值有重叠:axis=0
0
d2
d1
2
pd.concat([d1, d2], axis=0)
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
两个s(并排)DataFrame
axis=1
对于值,或者我们的意思是说:“沿着索引对齐并添加到列中”,1
columns
pd.concat([d1, d2], axis=1)
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
我们可以看到,生成的索引是索引的并集,生成的列是列的扩展。d1
d2
两个(或三个)与(堆叠)Series
axis=0
当组合在一起时,我们得到一个.除非所有被组合的名称都具有相同的名称,否则生成的名称将是。当我们打印出结果时,请注意 .当它不存在时,我们可以假设名称是 。pandas.Series
axis=0
pandas.Series
Series
None
Series
'Name: A'
Series
Series
None
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename('A'),
pd.concat( | [s1.rename('A'), | [s1.rename('A'), | s2.rename('B'),
[s1, s2]) | s2]) | s2.rename('A')]) | s3.rename('A')])
-------------- | --------------------- | ---------------------- | ----------------------
2 1 | 2 1 | 2 1 | 2 1
3 2 | 3 2 | 3 2 | 3 2
1 3 | 1 3 | 1 3 | 1 3
2 4 | 2 4 | 2 4 | 2 4
dtype: int64 | dtype: int64 | Name: A, dtype: int64 | 1 5
| | | 3 6
| | | dtype: int64
两个(或三个)与(并排)Series
axis=1
当组合时,它是我们引用的属性,以便在结果中推断列名。pandas.Series
axis=1
name
pandas.DataFrame
| | pd.concat(
| pd.concat( | [s1.rename('X'),
pd.concat( | [s1.rename('X'), | s2.rename('Y'),
[s1, s2], axis=1) | s2], axis=1) | s3.rename('Z')], axis=1)
---------------------- | --------------------- | ------------------------------
0 1 | X 0 | X Y Z
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 5.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 NaN
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN 6.0
混合和混合(堆叠)Series
DataFrame
axis=0
当执行 a 和 along 的串联时,我们将所有列转换为单列 s。Series
DataFrame
axis=0
Series
DataFrame
特别注意,这是沿 ;这意味着在对齐列的同时扩展索引(行)。在下面的示例中,我们看到索引变成了索引的不加区分的附加。这些列不会重叠,除非我使用参数强制命名列:axis=0
[2, 3, 2, 3]
Series
to_frame
pd.concat( |
[s1.to_frame(), d1]) | pd.concat([s1, d1])
------------------------- | ---------------------
0 A B C | 0 A B C
2 1.0 NaN NaN NaN | 2 1.0 NaN NaN NaN
3 2.0 NaN NaN NaN | 3 2.0 NaN NaN NaN
2 NaN 0.1 0.2 0.3 | 2 NaN 0.1 0.2 0.3
3 NaN 0.1 0.2 0.3 | 3 NaN 0.1 0.2 0.3
你可以看到的结果和我自己执行的结果是一样的。pd.concat([s1, d1])
to_frame
但是,我可以使用参数控制结果列的名称。重命名 with 方法不会控制生成的 .to_frame
Series
rename
DataFrame
# Effectively renames | |
# `s1` but does not align | # Does not rename. So | # Renames to something
# with columns in `d1` | # Pandas defaults to `0` | # that does align with `d1`
pd.concat( | pd.concat( | pd.concat(
[s1.to_frame('X'), d1]) | [s1.rename('X'), d1]) | [s1.to_frame('B'), d1])
---------------------------- | -------------------------- | ----------------------------
A B C X | 0 A B C | A B C
2 NaN NaN NaN 1.0 | 2 1.0 NaN NaN NaN | 2 NaN 1.0 NaN
3 NaN NaN NaN 2.0 | 3 2.0 NaN NaN NaN | 3 NaN 2.0 NaN
2 0.1 0.2 0.3 NaN | 2 NaN 0.1 0.2 0.3 | 2 0.1 0.2 0.3
3 0.1 0.2 0.3 NaN | 3 NaN 0.1 0.2 0.3 | 3 0.1 0.2 0.3
混合和(并排)Series
DataFrame
axis=1
这是相当直观的。 当属性不可用时,列名默认为此类对象的枚举。Series
Series
name
| pd.concat(
pd.concat( | [s1.rename('X'),
[s1, d1], | s2, s3, d1],
axis=1) | axis=1)
------------------- | -------------------------------
0 A B C | X 0 1 A B C
2 1 0.1 0.2 0.3 | 1 NaN 3.0 5.0 NaN NaN NaN
3 2 0.1 0.2 0.3 | 2 1.0 4.0 NaN 0.1 0.2 0.3
| 3 2.0 NaN 6.0 0.1 0.2 0.3
join
第三个参数是 join
,它描述生成的合并应该是外部合并(默认)还是内部合并。
join: {'inner', 'outer'}, default 'outer'
如何处理其他轴上的索引。
事实证明,没有 OR 选项可以处理两个以上的对象进行合并。left
right
pd.concat
在 和 的情况下,选项如下所示:d1
d2
outer
pd.concat([d1, d2], axis=1, join='outer')
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
inner
pd.concat([d1, d2], axis=1, join='inner')
A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6
join_axes
第四个论点是允许我们进行合并等等的事情。left
join_axes:Index 对象
列表 用于其他 n - 1 轴的特定索引,而不是执行内部/外部集合逻辑。
左合并
pd.concat([d1, d2, d3], axis=1, join_axes=[d1.index])
A B C B C D A B D
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
右合并
pd.concat([d1, d2, d3], axis=1, join_axes=[d3.index])
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
ignore_index
ignore_index:布尔值,默认为 False 如果为
True,则不要沿连接轴使用索引值。生成的轴将被标记为 0、...、n - 1。如果要连接连接对象,而连接轴没有有意义的索引信息,这将非常有用。请注意,在联接中仍会考虑其他轴上的索引值。
就像当我堆叠在 上面时一样,如果我不关心索引值,我可以重置它们或忽略它们。d1
d2
| pd.concat( | pd.concat(
| [d1, d2], | [d1, d2]
pd.concat([d1, d2]) | ignore_index=True) | ).reset_index(drop=True)
--------------------- | ----------------------- | -------------------------
A B C D | A B C D | A B C D
2 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6
使用时:axis=1
| pd.concat(
| [d1, d2], axis=1,
pd.concat([d1, d2], axis=1) | ignore_index=True)
------------------------------- | -------------------------------
A B C B C D | 0 1 2 3 4 5
1 NaN NaN NaN 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 3 0.1 0.2 0.3 NaN NaN NaN
keys
我们可以传递标量值或元组的列表,以便将元组或标量值分配给相应的 MultiIndex。传递列表的长度必须与连接的项目数的长度相同。
keys: sequence,默认 None
如果通过多个级别,则应包含元组。使用传递的键作为最外层来构造分层索引
axis=0
连接对象时(扩展索引)。Series
axis=0
这些键将成为 index 属性中对象的新初始级别。MultiIndex
# length 3 length 3 # length 2 length 2
# /--------\ /-----------\ # /----\ /------\
pd.concat([s1, s2, s3], keys=['A', 'B', 'C']) pd.concat([s1, s2], keys=['A', 'B'])
---------------------------------------------- -------------------------------------
A 2 1 A 2 1
3 2 3 2
B 1 3 B 1 3
2 4 2 4
C 1 5 dtype: int64
3 6
dtype: int64
但是,我们可以在参数中使用多个标量值来创建更深层次的 .在这里,我们传递长度 2 的 a 前面的两个新级别:keys
MultiIndex
tuples
MultiIndex
pd.concat(
[s1, s2, s3],
keys=[('A', 'X'), ('A', 'Y'), ('B', 'X')])
-----------------------------------------------
A X 2 1
3 2
Y 1 3
2 4
B X 1 5
3 6
dtype: int64
axis=1
沿列延伸时略有不同。当我们使用(见上文)时,除了现有索引之外,我们充当了水平。对于 ,我们指的是对象没有的轴,即属性。axis=0
keys
MultiIndex
axis=1
Series
columns
Series
axis=1
请注意,只要传递 no,命名 and 就很重要,但如果传递,它就会被覆盖。s1
s2
keys
keys
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename('U'),
pd.concat( | [s1, s2], | [s1.rename('U'), | s2.rename('V')],
[s1, s2], | axis=1, | s2.rename('V')], | axis=1,
axis=1) | keys=['X', 'Y']) | axis=1) | keys=['X', 'Y'])
-------------- | --------------------- | ---------------------- | ----------------------
0 1 | X Y | U V | X Y
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN
MultiIndex
with 和 Two withSeries
axis=1
pd.concat(
[s1, s2],
axis=1,
keys=[('W', 'X'), ('W', 'Y')])
-----------------------------------
W
X Y
1 NaN 3.0
2 1.0 4.0
3 2.0 NaN
DataFrame
axis=1
与示例一样,向 添加级别,但这次添加到存储在属性中的对象。axis=0
keys
MultiIndex
columns
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
axis=1, | axis=1,
keys=['X', 'Y']) | keys=[('First', 'X'), ('Second', 'X')])
------------------------------- | --------------------------------------------
X Y | First Second
A B C B C D | X X
1 NaN NaN NaN 0.4 0.5 0.6 | A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
| 3 0.1 0.2 0.3 NaN NaN NaN
Series
和DataFrame
axis=1
这很棘手。在这种情况下,当标量键值成为列时,它不能充当对象的唯一索引级别,同时还充当 .因此,Pandas 将再次使用对象的属性作为列名的来源。Series
MultiIndex
DataFrame
name
Series
pd.concat( | pd.concat(
[s1, d1], | [s1.rename('Z'), d1],
axis=1, | axis=1,
keys=['X', 'Y']) | keys=['X', 'Y'])
--------------------- | --------------------------
X Y | X Y
0 A B C | Z A B C
2 1 0.1 0.2 0.3 | 2 1 0.1 0.2 0.3
3 2 0.1 0.2 0.3 | 3 2 0.1 0.2 0.3
局限性和推断。keys
MultiIndex
Pandas 似乎只能从 name 推断列名,但在具有不同列级别数的数据框之间进行类似串联时,它不会填补空白。Series
d1_ = pd.concat(
[d1], axis=1,
keys=['One'])
d1_
One
A B C
2 0.1 0.2 0.3
3 0.1 0.2 0.3
然后将其与列对象中只有一个级别的另一个数据帧连接起来,Pandas 将拒绝尝试创建对象的元组,并将所有数据框组合在一起,就好像单个级别的对象、标量和元组一样。MultiIndex
pd.concat([d1_, d2], axis=1)
(One, A) (One, B) (One, C) B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
传递 a 而不是dict
list
传递字典时,将使用字典中的键作为参数。pandas.concat
keys
# axis=0 | # axis=1
pd.concat( | pd.concat(
{0: d1, 1: d2}) | {0: d1, 1: d2}, axis=1)
----------------------- | -------------------------------
A B C D | 0 1
0 2 0.1 0.2 0.3 NaN | A B C B C D
3 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
levels
这与参数结合使用。当保留为默认值时,Pandas 将获取结果的每个级别的唯一值,并将其用作结果属性中使用的对象。keys
levels
None
MultiIndex
index.levels
levels:序列列表,默认为“无
”,用于构造 MultiIndex 的特定级别(唯一值)。否则,它们将从密钥中推断出来。
如果 Pandas 已经推断出这些级别应该是什么,那么我们自己指定它有什么好处呢?我将举一个例子,并留给你去思考为什么这可能有用的其他原因。
例
根据文档,参数是序列列表。这意味着我们可以使用另一个序列作为这些序列之一。levels
pandas.Index
考虑由 和 串联的数据框:df
d1
d2
d3
df = pd.concat(
[d1, d2, d3], axis=1,
keys=['First', 'Second', 'Fourth'])
df
First Second Fourth
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
columns 对象的级别为:
print(df, *df.columns.levels, sep='\n')
Index(['First', 'Second', 'Fourth'], dtype='object')
Index(['A', 'B', 'C', 'D'], dtype='object')
如果我们在 a 中使用,我们会得到:sum
groupby
df.groupby(axis=1, level=0).sum()
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
但是,如果不是有另一个缺失的类别,则名为 和 呢?我希望将它们包含在聚合结果中?如果我们有一个 .我们可以提前用参数指定这一点。['First', 'Second', 'Fourth']
Third
Fifth
groupby
pandas.CategoricalIndex
levels
因此,让我们将其定义为:df
cats = ['First', 'Second', 'Third', 'Fourth', 'Fifth']
lvl = pd.CategoricalIndex(cats, categories=cats, ordered=True)
df = pd.concat(
[d1, d2, d3], axis=1,
keys=['First', 'Second', 'Fourth'],
levels=[lvl]
)
df
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
但是 columns 对象的第一级是:
df.columns.levels[0]
CategoricalIndex(
['First', 'Second', 'Third', 'Fourth', 'Fifth'],
categories=['First', 'Second', 'Third', 'Fourth', 'Fifth'],
ordered=True, dtype='category')
我们的总结如下所示:groupby
df.groupby(axis=1, level=0).sum()
First Second Third Fourth Fifth
1 0.0 1.5 0.0 2.4 0.0
2 0.6 1.5 0.0 0.0 0.0
3 0.6 0.0 0.0 2.4 0.0
names
这用于命名结果的级别。列表的长度应与生成的 .MultiIndex
names
MultiIndex
names: list, default 无
生成的层次结构索引中级别的名称
# axis=0 | # axis=1
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
keys=[0, 1], | axis=1, keys=[0, 1],
names=['lvl0', 'lvl1']) | names=['lvl0', 'lvl1'])
----------------------------- | ----------------------------------
A B C D | lvl0 0 1
lvl0 lvl1 | lvl1 A B C B C D
0 2 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
2 NaN 0.4 0.5 0.6 |
verify_integrity
一目了然的文档
verify_integrity:布尔值,默认为 False
检查新的串联轴是否包含重复项。相对于实际的数据连接,这可能非常昂贵。
由于连接生成的索引不是唯一的,因此完整性检查将失败。d1
d2
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
和
pd.concat([d1, d2], verify_integrity=True)
> ValueError:索引具有重叠值:[2]
评论
pd.concat(..., levels=[lvl]).groupby(axis=1, level=0).sum()
pd.concat(..., levels=[cats]).groupby(axis=1, level=0).sum()
levels
Passing a dict instead of a list
dict
lvl
cats
上一个:如何透视数据帧?
评论