pd。concat
Pandas的concat功能是合并实用程序的瑞士军刀。在各种各样的情况下它是有用的。现有文档遗漏了一些可选参数的细节。其中包括级别
和键
参数。我开始弄清楚这些论点的作用。
我将提出一个问题,它将作为进入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'])
我通过获得了预期的结果。多索引
用于我的列
对象:
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
但是,我想使用级别
参数留档:
级别:序列列表,默认为无。用于构建MultiIndex的特定级别(唯一值)。否则,它们将从密钥中推断出来。
所以我通过了
pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2']])
并得到一个KeyError
值错误:键d3不在级别索引(['d1','d2'], dtype='对象')
这是有道理的。我通过的水平不足以描述键所指示的必要水平。如果我没有通过任何东西,就像我上面所做的那样,水平是推断出来的(如留档中所述)。但是我还能用这个论点来更好地发挥作用吗?
如果我尝试这样做:
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
参数的意义是什么?我应该以不同的方式使用键吗?
我使用的是Python 3.6和Pandas 0.22。
在为自己回答这个问题的过程中,我学到了很多东西,我想整理一个例子目录和一些解释。
关于levels
参数的具体答案将在末尾给出。
链接到当前文档
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:序列、数据帧或面板对象的序列或映射如果传递dict,则排序的键将用作键参数,除非传递,否则在这种情况下将选择值(见下文)。任何None对象都将以静默方式删除,除非它们都是None,在这种情况下,将引发ValueError
Series
或DataFrame
对象的列表一起使用。dicing
也可以非常有用。map
时,也可以使用生成器,如map(f,list_of_df)
现在,我们将继续使用上面定义的一些DataFrame
和Series
对象的列表。稍后,我将展示如何利用字典来提供非常有用的多索引
结果。
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
我们遇到的第二个参数是ax
,其默认值为0
:
轴:{0/'index',1/'列'},默认值为0要连接的轴。
对于0
或index
的值,我们的意思是:沿着列对齐并添加到索引中。
如上所示,我们使用了ax=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
对于值1
或列
我们的意思是:“沿索引对齐并添加到列中”,
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
的列所扩展的列。
组合熊猫时。系列
沿轴=0
,我们得到一个熊猫。系列
.除非所有被组合的Series
具有相同的名称,否则生成的Series
的名称将为No
。当我们打印出结果的Series
时,请注意'Name: A'
。当它不存在时,我们可以假设Series
名称为无
。
| | | 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
组合熊猫时。序列
沿轴=1
,我们引用的是名称
属性,以推断结果中的列名。数据帧
。
| | 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
当沿着轴=0执行Series
和DataFrame
的串联时,我们将所有Series
转换为单列DataFrame
s。
请特别注意,这是沿轴=0的串联;这意味着在对齐列的同时扩展索引(行)。在下面的示例中,我们看到索引变成了
[2,3,2,3]
,这是索引的任意附加。除非我强制将系列
列的参数命名为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
来控制结果列的名称。使用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
这是相当直观的<当
列名默认为此类name
属性不可用时,code>SeriesSeries
对象的枚举。
| 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:{'inner','outer'},默认的'outer'
如何处理其他轴上的索引。
事实证明,没有
left
或right
选项作为pd。concat可以处理两个以上要合并的对象。
在
d1
和d2
的情况下,选项如下:
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
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:索引对象列表
用于其他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
忽略索引:布尔,默认为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
当使用轴=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
我们可以传递标量值或元组的列表,以便将元组或标量值分配给相应的MultiIndex。传递列表的长度必须与连接的项数相同。
键:序列,默认无
如果通过了多个级别,应该包含元组。使用传递的键作为最外面的级别构造层次索引
沿
轴=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
但是,我们可以在
key
参数中使用多个标量值来创建更深层次的MultiIndex
。在这里,我们将长度为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
沿着柱子延伸时有点不同。当我们使用
ax=0
(见上文)时,除了现有索引之外,我们的key
还充当MultiIndex
级别。对于ax=1
,我们指的是Series
对象没有的轴,即列
属性。
请注意,只要没有传递
键
,命名s1
和s2
就很重要,但是如果传递了键
,它就会被重写。
| | | 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
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
与
ax=0
示例一样,key
向MultiIndex
添加级别,但这一次是向存储在列
属性中的对象添加级别。
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
的MultiIndex
的第一级。所以Pandas将再次使用Series
对象的name
属性作为列名的来源。
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
Pandas似乎只从
系列
名称推断列名,但在具有不同列级别数的数据帧之间进行类似连接时,它不会填补空白。
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
然后将其与列对象中只有一个级别的另一个数据帧连接起来,熊猫将拒绝尝试制作
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
传递字典时,
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
保留为其默认值None
时,Pandas将获取生成的多索引
的每个级别的唯一值,并将其用作生成的索引中使用的对象。级别
属性。
级别:序列列表,默认无用于构造多索引的特定级别(唯一值)。否则,将从键中推断它们。
如果熊猫已经推断出这些水平应该是什么,那么我们自己指定它有什么好处呢?我将展示一个示例,并让您自己思考为什么这可能有用的其他原因。
根据文档,
levels
参数是序列列表。这意味着我们可以使用另一个熊猫。将
索引为这些序列之一。
考虑数据帧
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')
如果我们在
groupby
中使用sum
,我们得到:
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
聚合的结果中?如果我们有一个熊猫,我们可以做到这一点。分类索引
。我们可以使用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
这用于命名生成的
MultiIndex
的级别。name
列表的长度应与生成的MultiIndex
中的级别数相匹配。
名称:列表,默认无
结果层次索引中级别的名称
# 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 |
不言自明的文件
验证完整性:布尔值,默认值为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)
问题内容: 问题 如何使用? 什么是对的说法? 什么是对的说法? 有大量示例可以帮助解释如何使用所有参数吗? pandas的职能是合并后的公用事业公司的瑞士军刀。有用的情况多种多样。现有文档在一些可选参数上省略了一些细节。其中有和参数。我着手弄清楚这些论点的作用。 我将提出一个问题,将其作为的许多方面的门户。 考虑数据帧,以及: 如果我将这些与 对于我的对象,我得到了预期的结果: 但是,我想使用参
对于熊猫,有人知道,除了 (i) ,(以及的其他变体,如,等) (ii) (iii), 例如字符串列,总是有一个的? 或者,我想知道,在上面的列表中,除了(I)、(ii)和(iii)之外,是否有任何数据类型不使其成为对象?
问题内容: 如果我只是通过类似下面的函数,DataFrame.aggregate()和DataFrame.apply()函数之间的返回值的(类型)是否有任何区别 因为返回值看起来几乎一样。并且文档仅告诉: apply()-> apply:Series或DataFrame 聚合()->聚合:DataFrame 问题答案: agg有两种版本(aggregate的缩写)和适用:第一个版本在groupby
问题内容: in Pandas中in的功能到底是什么? 问题答案: 当你什么都不懂的时候是你的朋友。它清除了很多次疑问。 看一看: 输出: 当您使用的键将成为新数据框中的索引时。 将列设置为索引时,将获得以下好处: 速度。 当您基于索引列过滤值时,例如 ,因为索引列的散列会更快。不必遍历整个列即可找到。它将只计算的哈希值,并在1 go内找到它。 缓解。 当您可以使用较短和较快的语法,而不是较长和较
问题内容: 我只知道该功能。是否还有其他的功能类似,和? 问题答案: ~ ~ 我不确定是否等效。
问题内容: 支持多级列名: 此功能非常有用,因为它允许“水平”地将同一数据框的多个版本附加到区分实例的列名称的第一级(在我的示例中)。 想象一下我已经有一个这样的数据框: 有没有一种好方法可以向列名添加另一个级别,类似于行索引: 问题答案: 无需创建元组列表 采用: 结果数据框: 2014年1月25日起提出要求