问题
pd.concat
? levels
论据? keys
论据? Pandas 的
concat
函数是 Swiss Army knife合并公用事业。它有用的各种情况很多。现有文档遗漏了一些可选参数的一些细节。其中有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
argument documentation :levels: list of sequences, default None. Specific levels (unique values) to use for constructing a MultiIndex. Otherwise, they will be inferred from the keys.
所以我通过了
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
: 丢失的手册
Link To Current Documentation
导入和定义对象
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: a sequence or mapping of Series, DataFrame, or Panel objects If a dict is passed, the sorted keys will be used as the keys argument, unless it is passed, in which case the values will be selected (see below). Any None objects will be dropped silently unless they are all None in which case a ValueError will be raised
Series
列表一起使用或 DataFrame
对象。 dict
也非常有用。 map
时很有用如 map(f, list_of_df)
现在,我们将坚持列出一些
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
:axis: {0/’index’, 1/’columns’}, default 0 The axis to concatenate along.
两个
DataFrame
s 与 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
两个
DataFrame
s 与 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
(堆叠)执行
Series
的串联时和 DataFrame
沿axis=0
, 我们转换所有 Series
到单列DataFrame
s。请特别注意,这是沿
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
一样我自己。但是,我可以使用
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’
How to handle indexes on other axis(es).
原来,没有
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: list of Index objects
Specific indexes to use for the other n - 1 axes instead of performing inner/outer set logic.
左合并
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: boolean, default False
If True, do not use the index values along the concatenation axis. The resulting axis will be labeled 0, ..., n - 1. This is useful if you are concatenating objects where the concatenation axis does not have meaningful indexing information. Note the index values on the other axes are still respected in the join.
就像我堆叠时
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, default None
If multiple levels passed, should contain tuples. Construct hierarchical index using the passed keys as the outermost level
axis=0
连接时
Series
沿线对象 axis=0
(扩展索引)。那些键,成为
MultiIndex
的一个新的初始级别index 属性中的对象。 # 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
但是,我们可以在
keys
中使用多个标量值。创造更深层次的论据MultiIndex
.这里我们通过tuples
长度为 2 的前缀 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
注意命名
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
与 Series
和 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
这很棘手。在这种情况下,标量键值不能作为
Series
的唯一索引级别。对象,当它成为列同时也充当 MultiIndex
的第一级时为 DataFrame
.所以 Pandas 将再次使用 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 似乎只能从
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
传递一个
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
这与
keys
一起使用参数。当 levels
保留为其默认值 None
, Pandas 将采用结果 MultiIndex
的每个级别的唯一值并将其用作结果 index.levels
中使用的对象属性。levels: list of sequences, default None
Specific levels (unique values) to use for constructing a MultiIndex. Otherwise they will be inferred from the keys.
如果 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
列对象的级别是:
print(df, *df.columns.levels, sep='\n')
Index(['First', 'Second', 'Fourth'], dtype='object')
Index(['A', 'B', 'C', 'D'], dtype='object')
如果我们使用
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
但是列对象的第一级是:
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 None
Names for the levels in the resulting hierarchical index
# 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: boolean, default False
Check whether the new concatenated axis contains duplicates. This can be very expensive relative to the actual data concatenation.
因为连接
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]
关于python - Pandas 的 concat 函数中的 'levels' 、 'keys' 和名称参数是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49620538/