1.Numpy用来进行数值计算,是数据分析、机器学习的基础库。Pandas是数据分析的常用工具,也是基于Numpy的。
Numpy的核心概念是Ndarray,在Pandas中同样也有类似的核心概念:Series和DataFrame,由于Ndarray要求元素保持一样的数据类型,因此Numpy通常用来处理单一类型的数据,
而Series可以保存不同的数据类型,因此Pandas在处理表格和混杂类型的数据方面有着广泛的应用。
2.Series对象的创建
1.Series是Pandas中的一维数据结构,类似于Python中的列表和Numpy中的Ndarray,不同之处在于:Series是一维的,能存储不同类型的数据,有一组索引与元素对应。
下图的代码是Series的一个简单示例。
1.与Numpy类似,Pandas的引入也使用语句“import pandas as pd”,pd作为Pandas的别名是通用写法;
2.第3行创建了一个名为s1的series对象,本例中传入的是一个包含4个整型数值的列表,传入元组、字典都是可以的。
如果传入字典,字典的键key和值value将自动转换成series对象的索引和元素;
3.由s1的打印结果可知:series对象不仅包含数值,还包含一组索引,由于在创建series对象时没有指定索引,因此会默认使用非负整数当做索引。
2.在创建series对象时我们可以手动设置索引,如下图:
1.第3行我们创建了series对象s2,包含四个字符串,索引依次设置为'a','b','c','d';
2.打印的最后一行,s2元素类型dtype为object,注意Pandas中整型为int64,浮点型为float64,字符串、布尔型等其他数据类型都为object。
3.在series对象中,索引与元素之间是一种映射关系,元素在series对象中的有序存储是通过索引实现的,当传入字典创建series对象,
可以通过指定索引的方式对series对象中的元素进行排序和过滤。
1.对比字典scores和列表names我们发现:scores中的键顺序与names中元素顺序不一致,scores中没有的键为“tracy”的数据,names中没有“tom”;
2.第4行创建series对象s3时以索引(列表names)为依据,names中没有的元素(tom)将被过滤掉,scores中没有tracy的分数,将会被NaN代替;
3.从最后的打印结果可以看出:s3是以索引names排序的,由于NaN是浮点型,因此s3中的数据类型自动转换成float64。
3.Series元素的访问
1.Series对象的元素也可以像列表和ndarray一样通过[index]的方式访问,需要注意的是:如果在创建series对象时指定了整型之外的其他类型的索引,
默认的整数索引仍然可用。如下图的代码所示:使用s2[1]和s2['b']得到的值是完全相同的。
当然也可以使用 s2[1] = 'banana' 或 s2['b'] = 'banana' 语句在原地对series对象s2进行修改。
2.除了元素的值之外,索引也可以修改,下图中的示例将s2的索引由字符串型改为整型。
1.第5行将s2的索引修改为1到4的整数列表,修改后可以不用字符串索引访问元素,新的整数索引[1, 2, 3, 4]将覆盖默认的整数索引[0, 1, 2, 3],
此时第6行s2[1]将得到s2中的第一个元素“alpha”,而第7行s2[0]将报出索引错误(IndexError);
2.与修改元素一样,对索引的修改都是在原地进行,不会在内存中进行复制操作。
1.Pandas提供了concat、append、join、merge四种方法用于dataframe的拼接,其大致特点和区别见下表:
concat() pandas的顶级方法,提供了axis设置可用于dataframe间 行方向(增加行) 或 列方向(增加列) 进行内联或外联拼接操作
append() dataframe数据类型的方法,提供了行方向的拼接操作
join() dataframe数据类型的方法,提供了列方向的拼接操作,支持左联、右联、内联和外联四种操作类型
merge() pandas的顶级方法,提供了类似于SQL数据库连接操作的功能,支持左联、右联、内联和外联等全部四种SQL连接操作类型
2.pandas.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
keys=None, levels=None, names=None, verify_integrity=False,
copy=True)
1.常用参数说明:
objs:Series,DataFrame或Panel对象的序列或映射。如果传递了dict,则排序的键将用作键参数,除非它被传递,在这种情况下,将选择值(见下文)。
任何无对象将被静默删除,除非它们都是无,在这种情况下将引发一个ValueError。
axis:{0,1,...},默认为0。沿着连接的轴。拼接轴方向,默认为0,沿行拼接;若为1,沿列拼接。
join:{'inner','outer'},默认为“outer”。如何处理其他轴上的索引。outer为联合和inner为交集。
默认外联'outer',拼接另一轴所有的label,缺失值用NaN填充;内联'inner',只拼接另一轴相同的label。
ignore_index:boolean,default False。如果为True,请不要使用并置轴上的索引值。结果轴将被标记为0,...,n-1。
如果要连接其中并置轴没有有意义的索引信息的对象,这将非常有用。注意,其他轴上的索引值在连接中仍然受到尊重。
对index进行从0开始重新排序/排列
join_axes:Index对象列表。用于其他n-1轴的特定索引,而不是执行内部/外部设置逻辑。
指定需要拼接的轴的labels,可在join既不内联又不外联的时候使用
keys:序列,默认值无。使用传递的键作为最外层构建层次索引。如果为多索引,应该使用元组。多重索引
levels:序列列表,默认值无。用于构建MultiIndex的特定级别(唯一值)。否则,它们将从键推断。
names:list,default无。结果层次索引中的级别的名称。
verify_integrity:boolean,default False。检查新连接的轴是否包含重复项。这相对于实际的数据串联可能是非常昂贵的。
copy:boolean,default True。如果为False,请勿不必要地复制数据。
2.例子
>>> import pandas as pd
>>> def df_maker(cols, idxs):
return pd.DataFrame({c:[c+str(i) for i in idxs] for c in cols}, index=idxs)
>>> df1 = df_maker('abc',[1,2,3])
>>> df1
a b c
1 a1 b1 c1
2 a2 b2 c2
3 a3 b3 c3
>>> df2 = df_maker('cde',[3,4,5])
>>> df2
c d e
3 c3 d3 e3
4 c4 d4 e4
5 c5 d5 e5
>>> pd.concat([df1,df2]) # 默认沿axis=0,join=‘out’的方式进行concat
a b c d e
1 a1 b1 c1 NaN NaN
2 a2 b2 c2 NaN NaN
3 a3 b3 c3 NaN NaN
3 NaN NaN c3 d3 e3
4 NaN NaN c4 d4 e4
5 NaN NaN c5 d5 e5
>>> pd.concat([df1,df2], ignore_index=True) # 重新设定index(效果类似于pd.concat([df1,df2]).reset_index(drop=True))
a b c d e
0 a1 b1 c1 NaN NaN
1 a2 b2 c2 NaN NaN
2 a3 b3 c3 NaN NaN
3 NaN NaN c3 d3 e3
4 NaN NaN c4 d4 e4
5 NaN NaN c5 d5 e5
>>> pd.concat([df1,df2], axis=1) # 沿列进行合并
a b c c d e
1 a1 b1 c1 NaN NaN NaN
2 a2 b2 c2 NaN NaN NaN
3 a3 b3 c3 c3 d3 e3
4 NaN NaN NaN c4 d4 e4
5 NaN NaN NaN c5 d5 e5
>>> pd.concat([df1,df2], axis=1, join='inner') # 沿列进行合并,采用外联方式因为行中只有index=3是重复的,所以只有一行
a b c c d e
3 a3 b3 c3 c3 d3 e3
>>> pd.concat([df1,df2], axis=1, join_axes=[df1.index]) # 指定只取df1的index
a b c c d e
1 a1 b1 c1 NaN NaN NaN
2 a2 b2 c2 NaN NaN NaN
3 a3 b3 c3 c3 d3 e3
>>> from pandas import Index
>>> index = Index([1,2,4])
>>> pd.concat([df1,df2], axis=1, join_axes=[index]) # 自定义index
a b c c d e
1 a1 b1 c1 NaN NaN NaN
2 a2 b2 c2 NaN NaN NaN
4 NaN NaN NaN c4 d4 e4
>>> pd.concat([df1,df2], axis=0,keys=["第一组","第二组"]) # 通过key定义多重索引
a b c d e
第一组 1 a1 b1 c1 NaN NaN
2 a2 b2 c2 NaN NaN
3 a3 b3 c3 NaN NaN
第二组 3 NaN NaN c3 d3 e3
4 NaN NaN c4 d4 e4
5 NaN NaN c5 d5 e5
3.例子
In [1]: df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
...: 'B': ['B0', 'B1', 'B2', 'B3'],
...: 'C': ['C0', 'C1', 'C2', 'C3'],
...: 'D': ['D0', 'D1', 'D2', 'D3']},
...: index=[0, 1, 2, 3])
...:
In [2]: df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
...: 'B': ['B4', 'B5', 'B6', 'B7'],
...: 'C': ['C4', 'C5', 'C6', 'C7'],
...: 'D': ['D4', 'D5', 'D6', 'D7']},
...: index=[4, 5, 6, 7])
...:
In [3]: df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
...: 'B': ['B8', 'B9', 'B10', 'B11'],
...: 'C': ['C8', 'C9', 'C10', 'C11'],
...: 'D': ['D8', 'D9', 'D10', 'D11']},
...: index=[8, 9, 10, 11])
...:
In [4]: frames = [df1, df2, df3]
In [5]: result = pd.concat(frames)
4.KEY参数
result = pd.concat(frames, keys=['x', 'y', 'z'])
5.JOIN参数
1.默认join = 'outer',为取并集的关系
In [8]: df4 = pd.DataFrame({'B': ['B2', 'B3', 'B6', 'B7'],
...: 'D': ['D2', 'D3', 'D6', 'D7'],
...: 'F': ['F2', 'F3', 'F6', 'F7']},
...: index=[2, 3, 6, 7])
...:
In [9]: result = pd.concat([df1, df4], axis=1)
2.当设置join = 'inner',则说明为取交集
In [10]: result = pd.concat([df1, df4], axis=1, join='inner')
3.如果索引想从原始DataFrame重用确切索引:
In [11]: result = pd.concat([df1, df4], axis=1, join_axes=[df1.index]) #设置索引为df1的索引
3.pandas.append(self, other, ignore_index=False, verify_integrity=False)
1.常用参数说明:
other:另一个df
ignore_index:若为True,则对index进行从0开始重新排序/排列
verify_integrity:对index的唯一性进行验证,若有重复,报错。若已经设置了ignore_index,则该参数无效
2.例子
>>> import pandas as pd
>>> def df_maker(cols, idxs):
return pd.DataFrame({c:[c+str(i) for i in idxs] for c in cols}, index=idxs)
>>> df1 = df_maker('abc',[1,2,3])
>>> df1
a b c
1 a1 b1 c1
2 a2 b2 c2
3 a3 b3 c3
>>> df2 = df_maker('cde',[3,4,5])
>>> df2
c d e
3 c3 d3 e3
4 c4 d4 e4
5 c5 d5 e5
>>> df1.append(df2) # 效果类似于pd.concat([df1,df2])
a b c d e
0 a1 b1 c1 NaN NaN
1 a2 b2 c2 NaN NaN
2 a3 b3 c3 NaN NaN
3 NaN NaN c3 d3 e3
4 NaN NaN c4 d4 e4
5 NaN NaN c5 d5 e5
>>> df1.append(df2,ignore_index=True) # index重排,效果类似于pd.concat([df1, df2], ignore_index=True)
a b c d e
0 a1 b1 c1 NaN NaN
1 a2 b2 c2 NaN NaN
2 a3 b3 c3 NaN NaN
3 NaN NaN c3 d3 e3
4 NaN NaN c4 d4 e4
5 NaN NaN c5 d5 e5
>>> df1.append(df2,verify_integrity=True) # 因为两个df均有index=3,所以报错
4.pandas.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
1.常用参数说明:
on:参照的左边df列名key(可能需要先进行set_index操作),若未指明,按照index进行join
how:{‘left’, ‘right’, ‘outer’, ‘inner’}, 默认‘left’,即按照左边df的index(若声明了on,则按照对应的列);若为‘right’abs照左边的df
若‘inner’为内联方式;若为‘outer’为全连联方式。
sort:是否按照join的key对应的值大小进行排序,默认False
lsuffix,rsuffix:当left和right两个df的列名出现冲突时候,通过设定后缀的方式避免错误
2.例子
>>> import pandas as pd
>>> import numpy as np
>>> df3 = pd.DataFrame({'lkey':['foo','bar','baz','foo'], 'value':np.arange(1,5)})
>>> df3
lkey value
0 foo 1
1 bar 2
2 baz 3
3 foo 4
>>> df4 = pd.DataFrame({'rkey':['foo','bar','qux','bar'], 'value':np.arange(3,7)})
>>> df4
lkey value
0 foo 3
1 bar 4
2 qux 5
3 bar 6
>>> df3.join(df4) # 两者有相同的列名‘value’,所以报错
>>> df3.join(df4 , lsuffix='_df3', rsuffix='_df4') # 通过添加后缀避免冲突
lkey value_df3 rkey value_df4
0 foo 1 foo 3
1 bar 2 bar 4
2 baz 3 qux 5
3 foo 4 bar 6
>>> df3.set_index('lkey').join(df4.set_index('rkey'), how='outer',lsuffix='_df3',rsuffix='_df4') # 可以通过将两边的key进行set_index
value_df3 value_df4
bar 2.0 4.0
bar 2.0 6.0
baz 3.0 NaN
foo 1.0 3.0
foo 4.0 3.0
qux NaN 5.0
>>> df3.join(df4.set_index('rkey'), on='lkey',lsuffix='_df3',rsuffix='_df4') # 也可以通过设置后边df中key,并通过on与指定的左边df中的列进行合并,返回的index不变
lkey value_df3 value_df4
0 foo 1 3.0
1 bar 2 4.0
1 bar 2 6.0
2 baz 3 NaN
3 foo 4 3.0
5.pandas.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
left_index=False, right_index=False, sort=False,
suffixes=('_x', '_y'), copy=True, indicator=False, validate=None):
1.既可作为pandas的顶级方法使用,也可作为DataFrame数据结构的方法进行调用
2.常用参数说明:
how:{'left’, ‘right’, ‘outer’, ‘inner’}, 默认‘inner’,类似于SQL的内联。
'left’类似于SQL的左联;'right’类似于SQL的右联; outer’类似于SQL的全联。
on:进行合并的参照列名,必须一样。若为None,方法会自动匹配两张表中相同的列名
left_on: 左边df进行连接的列
right_on: 右边df进行连接的列
suffixes: 左、右列名称前缀
validate:默认None,可定义为“one_to_one” 、“one_to_many” 、“many_to_one”和“many_to_many”,即验证是否一对一、一对多、多对一或 多对多关系
3.SQL语句复习:
内联:SELECT a.*, b.* from table1 as a inner join table2 as b on a.ID=b.ID
左联:SELECT a.*, b.* from table1 as a left join table2 as b on a.ID=b.ID
右联:SELECT a.*, b.* from table1 as a right join table2 as b on a.ID=b.ID
全联:SELECT a.*, b.* from table1 as a full join table2 as b on a.ID=b.ID
4.例子
>>> import pandas as pd
>>> df3 = pd.DataFrame({'lkey':['foo','bar','baz','foo'], 'value':np.arange(1,5)})
>>> df3
lkey value
0 foo 1
1 bar 2
2 baz 3
3 foo 4
>>> df4 = pd.DataFrame({'rkey':['foo','bar','qux','bar'], 'value':np.arange(3,7)})
>>> df4
lkey value
0 foo 3
1 bar 4
2 qux 5
3 bar 6
>>> pd.merge(df3,df4) # on为None,自动找寻相同的列名,即为'value',且默认为内联
lkey value rkey
0 baz 3 foo
1 foo 4 bar
>>> pd.merge(df3,df4,how='outer') # 外联模式下
lkey value rkey
0 foo 1 NaN
1 bar 2 NaN
2 baz 3 foo
3 foo 4 bar
4 NaN 5 qux
5 NaN 6 bar
>>> pd.merge(df3, df4, left_on='lkey',right_on='rkey') # 默认内联,2个foo*2个bar
lkey value_x rkey value_y
0 foo 1 foo 3
1 foo 4 foo 3
2 bar 2 bar 4
3 bar 2 bar 6
>>> pd.merge(df3, df4, left_on='lkey',right_on='rkey', how='left') # 以左边的df3为标准进行连接
lkey value_x rkey value_y
0 foo 1 foo 3.0
1 bar 2 bar 4.0
2 bar 2 bar 6.0
3 baz 3 NaN NaN
4 foo 4 foo 3.0
>>> pd.merge(df3, df4, left_on='lkey',right_on='rkey', how='right') # 以右边的df4为标准进行连接
lkey value_x rkey value_y
0 foo 1.0 foo 3
1 foo 4.0 foo 3
2 bar 2.0 bar 4
3 bar 2.0 bar 6
4 NaN NaN qux 5
>>> pd.merge(df3, df4, left_on='lkey',right_on='rkey', how='outer') # 全连接
lkey value_x rkey value_y
0 foo 1.0 foo 3.0
1 foo 4.0 foo 3.0
2 bar 2.0 bar 4.0
3 bar 2.0 bar 6.0
4 baz 3.0 NaN NaN
5 NaN NaN qux 5.0