数据规整化:清理、转化、合并、重塑
合并数据集
- pandas.merge 可根据一个或多个键将不同 DataFrame 中的行连接起来。
- pandas.concat 可以沿着一条轴将多个对象堆叠到一起
- 实例方法 combine_first 可以用一个对象中的值填充另一个对象中对应位置的缺失值
数据库风格的 DataFrame 合并
数据集的合并(merge)和连接(join)运算时通过一个或多个键将行链接起来的。
df1 = DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df2 = DataFrame({'key': ['a', 'b', 'd'],
'data2': range(3)})
df1
Out:
data1 key
0 0 b
1 1 b
2 2 a
3 3 c
4 4 a
5 5 a
6 6 b
df2
Out:
data2 key
0 0 a
1 1 b
2 2 d
pd.merge(df1, df2)
Out:
data1 key data2
0 0 b 1
1 1 b 1
2 6 b 1
3 2 a 0
4 4 a 0
5 5 a 0
我们并没有指定要用哪个列进行连接,如果没有指定,merge 就会将重叠列的列名当做键,但最好还是指定一下:
pd.merge(df1, df2, on='key')
如果两个对象的列名不同,可以分别指定:
df3 = DataFrame({'lkey': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df4 = DataFrame({'rkey': ['a', 'b', 'd'],
'data2': range(3)})
pd.merge(df3, df4, left_on='lkey', right_on='rkey')
Out:
data1 lkey data2 rkey
0 0 b 1 b
1 1 b 1 b
2 6 b 1 b
3 2 a 0 a
4 4 a 0 a
5 5 a 0 a
默认情况下,merge 做的是 inner 连接;结果中的键是交集。其他方式还有 left、right 以及 outer。
pd.merge(df1, df2, how='outer')
Out:
data1 key data2
0 0 b 1
1 0 b 3
2 1 b 1
3 1 b 3
4 5 b 1
5 5 b 3
6 2 a 0
7 2 a 2
8 4 a 0
9 4 a 2
10 3 c NaN
11 NaN d 4
要根据多个键进行合并,传入一个由列名组成的列表即可:
left = DataFrame({'key1': ['foo', 'foo', 'bar'],
'key2': ['one', 'two', 'one'],
'lval': [1, 2, 3]})
right = DataFrame({'key1': ['foo', 'foo', 'bar', 'bar'],
'key2': ['one', 'one', 'one', 'two'],
'rval': [4, 5, 6, 7]})
pd.merge(left, right, on=['key1', 'key2'], how='outer')
Out:
key1 key2 lval rval
0 foo one 1 4
1 foo one 1 5
2 foo two 2 NaN
3 bar one 3 6
4 bar two NaN 7
对于合并运算要考虑的最后一个问题室对重复列名的处理,merge 有一个使用的 suffixes 选项,用于指定附加到左右两个 DataFrame 对象的重叠列名上的字符串:
pd.merge(left, right, on='key1')
Out:
key1 key2_x lval key2_y rval
0 foo one 1 one 4
1 foo one 1 one 5
2 foo two 2 one 4
3 foo two 2 one 5
4 bar one 3 one 6
5 bar one 3 two 7
pd.merge(left, right, on='key1', suffixes=('_left', '_right'))
Out:
key1 key2_left lval key2_right rval
0 foo one 1 one 4
1 foo one 1 one 5
2 foo two 2 one 4
3 foo two 2 one 5
4 bar one 3 one 6
5 bar one 3 two 7
merge 函数的参数
参数 | 说明 |
---|---|
left | 参与合并的左侧 DataFrame |
right | 参与合并的右侧 DataFrame |
how | inner、outer、left、right其中之一。默认为 inner |
on | 用于连接的列名 |
left_on | 左侧 DataFrame 中用作连接键的列 |
right_on | 右侧 DataFrame 中用作连接键的列 |
left_index | 布尔型,将左侧的行索引用作其连接键 |
right_index | 同上 |
sort | 根据连接键对合并后的数据进行排序,默认为 True。有时在处理大数据时,禁用该选项可获得更好的性能 |
suffixes | 字符串值元组,用于追加到重叠列名的末尾,默认为(‘_x’,‘_y’) |
copy | 默认为 True,复制结果集 |
索引上的合并
可以传入 left_index=True 或 right_index=True 以说明索引应该被用作连接键:
left1 = DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'],
'value': range(6)})
right1 = DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
left
Out:
key value
0 a 0
1 b 1
2 a 2
3 a 3
4 b 4
5 c 5
right
Out:
group_val
a 3.5
b 7.0
pd.merge(left1, right1, left_on='key', right_index=True)
Out:
key value group_val
0 a 0 3.5
2 a 2 3.5
3 a 3 3.5
1 b 1 7.0
4 b 4 7.0
轴向连接
NumPy 有一个用于合并原始 NumPy 数组的 concatenation 函数:
arr = np.arange(12).reshape((3, 4))
arr
Out:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
np.concatenate([arr, arr], axis=1)
Out:
array([[ 0, 1, 2, 3, 0, 1, 2, 3],
[ 4, 5, 6, 7, 4, 5, 6, 7],
[ 8, 9, 10, 11, 8, 9, 10, 11]])
对于 pandas 对象(如 Seri 和 DataFrame),带有标签的轴能够进一步推广数组的连接运算。具体来说,需要考虑一下问题:
- 如果各对象其他轴上的索引不同,那些轴应该是做并集还是交集?
- 结果对象中的分组需要各不相同吗?
- 用于连接的轴重要吗?
pandas 的 concat 函数提供了一种能够解决这些问题的可靠方式。假设三个没有重叠索引的 Series:
s1 = Series([0, 1], index=['a', 'b'])
s2 = Series([2, 3, 4], index=['c', 'd', 'e'])
s3 = Series([5, 6], index=['f', 'g'])
pd.concat([s1, s2, s3])
Out:
a 0
b 1
c 2
d 3
e 4
f 5
g 6
dtype: int64
默认情况下,concat 是在 axis = 0 上工作的,如果传入 axis = 1,则结果会变成一个 DataFrame:
pd.concat([s1,s2,s3],axis=1)
Out:
0 1 2
a 0 NaN NaN
b 1 NaN NaN
c NaN 2 NaN
d NaN 3 NaN
e NaN 4 NaN
f NaN NaN 5
g NaN NaN 6
这种情况下,另外一条轴上没有重叠,从索引的有序并集上就可以看出来。传入 join = 'inner' 即可得到它们的交集:
s4 = pd.concat([s1 * 5, s3])
pd.concat([s1, s4], axis=1)
Out:
0 1
a 0 0
b 1 5
f NaN 5
g NaN 6
pd.concat([s1, s4], axis=1, join='inner')
Out:
0 1
a 0 0
b 1 5
```
对于 DataFrame 来说:
```python
df1 = DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'],
columns=['one', 'two'])
df2 = DataFrame(5 + np.arange(4).reshape(2, 2), index=['a', 'c'],
columns=['three', 'four'])
pd.concat([df1, df2], axis=1, keys=['level1', 'level2'])
# 或者 pd.concat({'level1': df1, 'level2': df2}, axis=1)
Out:
level1 level2
one two three four
a 0 1 5 6
b 2 3 NaN NaN
c 4 5 7 8
```
> concat 函数的参数
参数 | 说明
--- | ---
objs | 参与连接的 pandas 对象的列表或字典。
axis | 指明连接的轴向,默认为0
join | “inner”、“outer”其中之一,默认为“outer”
join_axes | 指明用于其他 n-1 条轴的索引,不执行并集/交集运算
keys | 与连接对象有关的值,用于形成连接轴向上的层次索引。可以是任意值得列表或数组、元组数组、数组列表(如果 levels 设置成多级数据的话)
levels | 指定用作层次化级别的名称,如果设置了keys和(或)levels的话
verify_integrity | 检查结果对象新轴上的重复情况,如果发现则引发一场。默认(False)允许重复
ignore_index | 不保留连接轴上的索引,产生一组新索引 range(total_length)
### 合并重叠数据
要合并两个索引全部或部分重叠的数据集,可以使用 NumPy 的 where 函数,它用于表达一种矢量化的 if-else:
```python
a = Series([np.nan, 2.5, np.nan, 3.5, 4.5, np.nan],
index=['f', 'e', 'd', 'c', 'b', 'a'])
b = Series(np.arange(len(a), dtype=np.float64),
index=['f', 'e', 'd', 'c', 'b', 'a'])
b[-1] = np.nan
a
Out:
f NaN
e 2.5
d NaN
c 3.5
b 4.5
a NaN
dtype: float64
b
Out:
f 0
e 1
d 2
c 3
b 4
a NaN
dtype: float64
np.where(pd.isnull(a), b, a)
Out:
array([ 0. , 2.5, 2. , 3.5, 4.5, nan])
```
Series 有一个 combine_first 方法,实现的也是一样的功能,而且会进行数据对齐:
```python
b[:-2].combine_first(a[2:])
Out:
a NaN
b 4.5
c 3.0
d 2.0
e 1.0
f 0.0
dtype: float64
```
对于 DataFrame,combine_first 也会做同样的事情。
## 重塑和轴向旋转
有许多用于重新排列表格型数据的基础运算。这些函数也称作重塑(reshape)或轴向旋转(pivot)运算。
### 重塑层次化索引
DataFrame 的层次化重塑:
> - stack:将数据的列“旋转”为行。
> - unstack:将数据的行“旋转”为列。
```python
data = DataFrame(np.arange(6).reshape((2, 3)),
index=pd.Index(['Ohio', 'Colorado'], name='state'),
columns=pd.Index(['one', 'two', 'three'], name='number'))
data
Out:
number one two three
state
Ohio 0 1 2
Colorado 3 4 5
result = data.stack()
result
Out:
state number
Ohio one 0
two 1
three 2
Colorado one 3
two 4
three 5
dtype: int32
result.unstack()
Out:
number one two three
state
Ohio 0 1 2
Colorado 3 4 5
```
默认情况下,unstack 操作的是最内层(stack 也是),但可以传入分层级别的编号或名称即可对其他级别进行 unstack 操作。
如果不是所有的级别值都能在各分组中找到的话,则 unstack 操作可能会引入缺失数据;而 stack 则会过滤缺失数据:
```
s1 = Series([0, 1, 2, 3], index=['a', 'b', 'c', 'd'])
s2 = Series([4, 5, 6], index=['c', 'd', 'e'])
data2 = pd.concat([s1, s2], keys=['one', 'two'])
data2
Out:
one a 0
b 1
c 2
d 3
two c 4
d 5
e 6
dtype: int64
data2.unstack()
Out:
a b c d e
one 0 1 2 3 NaN
two NaN NaN 4 5 6
data2.unstack().stack()
Out:
one a 0
b 1
c 2
d 3
two c 4
d 5
e 6
dtype: float64
```
### 将“长格式”旋转为“宽格式”
所谓的“长格式”如下:
```python
ldata[:10]
Out:
date item value
0 1959-03-31 realgdp 2710.349
1 1959-03-31 infl 0.000
2 1959-03-31 unemp 5.800
3 1959-06-30 realgdp 2778.801
4 1959-06-30 infl 2.340
5 1959-06-30 unemp 5.100
6 1959-09-30 realgdp 2775.488
7 1959-09-30 infl 2.740
8 1959-09-30 unemp 5.300
9 1959-12-31 realgdp 2785.204
```
DataFrame 的 pivot 方法可以转换成如下的“宽格式”:
```python
pivoted = ldata.pivot('date', 'item', 'value')
pivoted.head()
Out:
item infl realgdp unemp
date
1959-03-31 0.00 2710.349 5.8
1959-06-30 2.34 2778.801 5.1
1959-09-30 2.74 2775.488 5.3
1959-12-31 0.27 2785.204 5.6
1960-03-31 2.31 2847.699 5.2
```
前两个参数分别用作行和列索引的列名,最后一个参数则是用于填充 DataFrame 的数据列的列名。假设有两个需要参与重塑的数据列:
```python
ldata['value2'] = np.random.randn(len(ldata))
ldata[:10]
Out:
date item value value2
0 1959-03-31 realgdp 2710.349 -0.204708
1 1959-03-31 infl 0.000 0.478943
2 1959-03-31 unemp 5.800 -0.519439
3 1959-06-30 realgdp 2778.801 -0.555730
4 1959-06-30 infl 2.340 1.965781
5 1959-06-30 unemp 5.100 1.393406
6 1959-09-30 realgdp 2775.488 0.092908
7 1959-09-30 infl 2.740 0.281746
8 1959-09-30 unemp 5.300 0.769023
9 1959-12-31 realgdp 2785.204 1.246435
```
如果忽略最后一个参数,得到的 DataFrame 就会带有层次化的列:
```python
pivoted = ldata.pivot('date', 'item')
pivoted[:5]
Out:
value value2
item infl realgdp unemp infl realgdp unemp
date
1959-03-31 0.00 2710.349 5.8 0.478943 -0.204708 -0.519439
1959-06-30 2.34 2778.801 5.1 1.965781 -0.555730 1.393406
1959-09-30 2.74 2775.488 5.3 0.281746 0.092908 0.769023
1959-12-31 0.27 2785.204 5.6 1.007189 1.246435 -1.296221
1960-03-31 2.31 2847.699 5.2 0.228913 0.274992 1.352917
```
利用 set_index 创建层次化索引,再用 unstack 重塑可以得到同样的效果:
```python
unstacked = ldata.set_index(['date', 'item']).unstack('item')
unstacked[:5]
Out:
value value2
item infl realgdp unemp infl realgdp unemp
date
1959-03-31 0.00 2710.349 5.8 0.478943 -0.204708 -0.519439
1959-06-30 2.34 2778.801 5.1 1.965781 -0.555730 1.393406
1959-09-30 2.74 2775.488 5.3 0.281746 0.092908 0.769023
1959-12-31 0.27 2785.204 5.6 1.007189 1.246435 -1.296221
1960-03-31 2.31 2847.699 5.2 0.228913 0.274992 1.352917
```
## 数据转换
主要是数据的过滤、清理以及其他的转换工作。
### 移除重复数据
DataFrame 的 duplicated 方法返回一个布尔型 Series,表示各行是否是重复行:
```python
data = DataFrame({'k1': ['one'] * 3 + ['two'] * 4,
'k2': [1, 1, 2, 3, 3, 4, 4]})
data
Out:
k1 k2
0 one 1
1 one 1
2 one 2
3 two 3
4 two 3
5 two 4
6 two 4
data.duplicated()
Out:
0 False
1 True
2 False
3 False
4 True
5 False
6 True
dtype: bool
```
DataFrame 的 drop_duplicates 方法返回一个移除了重复行的 DataFrame:
```python
data.drop_duplicates()
Out:
k1 k2
0 one 1
2 one 2
3 two 3
5 two 4
```
这两个方法默认判断全部列,也可以指定部分列进行重复项判断:
```python
data['v1'] = range(7)
data.drop_duplicates(['k1'])
Out:
k1 k2 v1
0 one 1 0
3 two 3 3
```
duplicated 和 drop_duplicates 默认保留的是第一个出现的值组合。传入 keep='last' 则保留最后一个:
```python
data.drop_duplicates(['k1', 'k2'], keep='last')
Out:
k1 k2 v1
1 one 1 1
2 one 2 2
4 two 3 4
6 two 4 6
```
### 利用函数或映射进行数据转换
以下是有关肉类的数据:
```python
data = DataFrame({'food': ['bacon', 'pulled pork', 'bacon', 'Pastrami',
'corned beef', 'Bacon', 'pastrami', 'honey ham',
'nova lox'],
'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
data
Out:
food ounces
0 bacon 4.0
1 pulled pork 3.0
2 bacon 12.0
3 Pastrami 6.0
4 corned beef 7.5
5 Bacon 8.0
6 pastrami 3.0
7 honey ham 5.0
8 nova lox 6.0
```
如果要添加一列表示该肉类食物来源的动物类型,Series 的 map 方法可以接受一个函数或含有映射关系的字典对象:
```python
meat_to_animal = {
'bacon': 'pig',
'pulled pork': 'pig',
'pastrami': 'cow',
'corned beef': 'cow',
'honey ham': 'pig',
'nova lox': 'salmon'
}
data['animal'] = data['food'].map(str.lower).map(meat_to_animal)
data
Out:
food ounces animal
0 bacon 4.0 pig
1 pulled pork 3.0 pig
2 bacon 12.0 pig
3 Pastrami 6.0 cow
4 corned beef 7.5 cow
5 Bacon 8.0 pig
6 pastrami 3.0 cow
7 honey ham 5.0 pig
8 nova lox 6.0 salmon
```
也可以传入一个能够完成全部工作的函数:
```python
data['animal'] = data['food'].map(lambda x: meat_to_animal[x.lower()])
```
### 替换值
利用 fillna 方法填充缺失数据可以看做值替换的一种特殊情况。虽然前面提到的 map 可以修改对象的数据子集,而 replace
则提供了一种实现该功能的更简单、更灵活的方式。replace 可以传入单个元素、列表或字典。
### 重命名轴索引
跟 Series 中的值一样,轴标签页可以通过函数或映射进行转换,从而得到一个新对象。轴还可以被就地修改,而无需新建一个数据结构。
```python
data = DataFrame(np.arange(12).reshape((3, 4)),
index=['Ohio', 'Colorado', 'New York'],
columns=['one', 'two', 'three', 'four'])
data.index = data.index.map(str.upper)
data
Out:
one two three four
OHIO 0 1 2 3
COLORADO 4 5 6 7
NEW YORK 8 9 10 11
```
如果想要创建数据集的转换板(而不是修改原始数据),比较实用的方法是 rename:
```python
data.rename(index=str.title, columns=str.upper)
Out:
ONE TWO THREE FOUR
Ohio 0 1 2 3
Colorado 4 5 6 7
New York 8 9 10 11
```
rename 可以结合字典型对象实现对部分轴标签的更新,同时可以传入 inplace=True 就地修改某个数据集。
### 离散化和面元划分
为了便于分析,连续数据常常被离散化或拆分为“面元”(bin)。假设有一组人员数据,将它们划分为不同的年龄组。将数据划分为“18到25”、
“26到35”、“35到60”以及“60以上”几个面元,需要使用到 pandas 的 cut 函数:
```python
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
bins = [18, 25, 35, 60, 100]
cats = pd.cut(ages, bins)
cats
Out:
[(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
Length: 12
Categories (4, object): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
```
pandas 返回的是一个特殊化的 Categorical 对象,它包含一个表示不同分类名称的 categories 数组以及一个为年龄数据进行标号的
codes 属性:
```python
cats.codes
Out:
array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8)
cats.categories
Out:
Index([u'(18, 25]', u'(25, 35]', u'(35, 60]', u'(60, 100]'], dtype='object')
pd.value_counts(cats)
Out:
(18, 25] 5
(35, 60] 3
(25, 35] 3
(60, 100] 1
dtype: int64
```
跟“区间”的数学符号一样,圆括号表示开端,而方括号则表示闭端(包括)。哪边是闭端可以通过 right=False 进行修改。也可以
设置自己的面元名称,将 labels 选项设置为一个列表或数组即可:
```python
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
pd.cut(ages, bins, labels=group_names)
Out:
[Youth, Youth, Youth, YoungAdult, Youth, ..., YoungAdult, Senior, MiddleAged, MiddleAged, YoungAdult]
Length: 12
Categories (4, object): [Youth < YoungAdult < MiddleAged < Senior]
```
如果向 cut 传入的是面元的数量而不是确切的面元边界,则它会根据数据的最小值和最大值计算等长面元。
qcut 是一个非常类似于 cut 的函数,它可以根据样本分位数对数据进行面元划分:
```python
data = np.random.randn(1000) # Normally distributed
cats = pd.qcut(data, 4) # Cut into quartiles
cats
Out:
[(0.644, 3.26], [-3.745, -0.635], (0.644, 3.26], [-3.745, -0.635], (-0.022, 0.644], ..., (-0.022, 0.644], (0.644, 3.26], (-0.635, -0.022], (0.644, 3.26], (-0.635, -0.022]]
Length: 1000
Categories (4, object): [[-3.745, -0.635] < (-0.635, -0.022] < (-0.022, 0.644] < (0.644, 3.26]]
```
跟 cut 一样,也可以设置自定义的分位点(0到1之间的数值,包括端点)。
### 检测和过滤异常值
异常值的过滤或变换运算在很大程度上其实就是数组运算。下面是一个含有正态分布数据的 DataFrame:
```python
np.random.seed(12345)
data = DataFrame(np.random.randn(1000, 4))
data.describe()
Out:
0 1 2 3
count 1000.000000 1000.000000 1000.000000 1000.000000
mean -0.067684 0.067924 0.025598 -0.002298
std 0.998035 0.992106 1.006835 0.996794
min -3.428254 -3.548824 -3.184377 -3.745356
25% -0.774890 -0.591841 -0.641675 -0.644144
50% -0.116401 0.101143 0.002073 -0.013611
75% 0.616366 0.780282 0.680391 0.654328
max 3.366626 2.653656 3.260383 3.927528
```
找出某列中绝对值超过3的值:
```python
col = data[3]
col[np.abs(col)>3]
```
要选出全部含有“超过3或-3的值”的行,可以利用 DataFrame 以及 any 方法:
```
data[(np.abs(data) > 3).any(1)]
```
然后可以将值限制在区间[-3,3]以内(np.sign 这个 ufunc 返回的是一个由1和-1组成的数组,表示原始值得符号。):
```
data[np.abs(data) > 3] = np.sign(data) * 3
```
### 排列和随机抽样
利用 numpy.random.permutation 函数可以轻松实现对 Series 或 DataFrame 的列的排列工作。通过需要排列的轴的长度调用
permutation,可产生一个表示新顺序的整数数组:
```
df = DataFrame(np.arange(5 * 4).reshape((5, 4)))
sampler = np.random.permutation(5)
sampler
Out:
array([1, 0, 2, 3, 4])
df
Out:
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
4 16 17 18 19
```
然后就可以在基于 ix 的索引操作或 take 函数中使用该数组了:
```python
df.take(sampler)
Out:
0 1 2 3
1 4 5 6 7
0 0 1 2 3
2 8 9 10 11
3 12 13 14 15
4 16 17 18 19
```
### 计算指标/哑变量
一种常用于统计建模或机器学习的转换方式是:将分类变量转换为“哑变量矩阵”或“指标矩阵”。如果 DataFrame 的某一列中含有 k 个
不同的值,则可以派生出一个 k 列矩阵或 DataFrame(其值全为1和0)。pandas 有一个 get_dummies 函数可以实现该功能。
```python
df = DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
'data1': range(6)})
pd.get_dummies(df['key'])
Out:
a b c
0 0 1 0
1 0 1 0
2 1 0 0
3 0 0 1
4 1 0 0
5 0 1 0
```
结合 get_dummies 和诸如 cut 之类的离散化函数:
```python
values = np.random.rand(10)
values
Out:
array([ 0.046 , 0.5346, 0.8187, 0.3951, 0.3464, 0.0534, 0.9332,
0.1028, 0.5361, 0.0043])
bins = [0, 0.2, 0.4, 0.6, 0.8, 1]
pd.get_dummies(pd.cut(values, bins))
Out:
(0, 0.2] (0.2, 0.4] (0.4, 0.6] (0.6, 0.8] (0.8, 1]
0 1 0 0 0 0
1 0 0 1 0 0
2 0 0 0 0 1
3 0 1 0 0 0
4 0 1 0 0 0
5 1 0 0 0 0
6 0 0 0 0 1
7 1 0 0 0 0
8 0 0 1 0 0
9 1 0 0 0 0
```
## 字符串操作
Python 能够成为流行的数据处理语言,部分原因是其简单易用的字符串和文本处理功能。大部分文本运算直接做成了字符串对象的内置
方法。对于更为复杂的模式匹配和文本操作,则可能需要用到正则表达式。pandas 对此进行了加强。
### 字符串对象的方法
> Python内置的字符串方法
方法 | 说明
--- | ---
count | 返回子串在字符串中的出现次数(非重叠)
endswith、startswith | 如果字符串以某个后缀(或前缀)结尾,则返回True
join | 将字符串用作连接其他字符串序列的分隔符
index | 如果字符串中找到子串,则返回子串的第一个字符所在的位置;如果没有找到,则引发ValueError
find | 如果字符串中找到子串,则返回第一个发现的子串的第一个字符所在的位置;如果没有找到,则返回-1
rfind | 如果字符串中找到子串,则返回最后一个发现的子串的第一个字符所在的位置;如果没有找到,则返回-1
replace | 用另一个字符串替换指定子串
strip、rstrip、lstrip | 去除空白符(包括换行符)。
split | 通过指定的分隔符将字符串拆分为一组子串
lower、upper | 分别将字母字符转换为小写或大写
ljust、rjust | 用空格(或其他字符)填充字符串的空白侧以返回符合最低宽度的字符串
### 正则表达式
> 正则表达式方法
方法 | 说明
--- | ---
findall、finditer | 返回字符串中所有的费重叠匹配模式,findall 返回的是由所有模式组成的列表,而 finditer 则通过一个迭代器逐个返回
match | 从字符串起始位置匹配模式,还可以对模式各部分进行分组。
search | 扫描整个字符串以匹配模式,其匹配项可以位于字符串的任意位置。
split | 根据找到的模式将字符串拆分为数段
sub、subn | 将字符串中所有的(sub)或前n个(subn)模式替换为指定表达式
### pandas 中矢量化的字符串函数
> 适量化的字符串方法
方法 | 说明
--- | ---
cat | 实现元素级的字符串连接操作,可指定分隔符
contains | 返回表示各字符串是否含有指定模式的布尔型数组
count | 模式的出现次数
endswith、startswith | 相当于对各个元素执行 x.endswith(pattern) 或 x.startswith(pattern)
findall | 计算各字符串的模式列表
get | 获取各元素的第i个字符
join | 根据指定的分隔符将 Series 中各元素的宇符串连接起来
len | 计算各字符串的长度
lower、upper | 转换大小写。相当于对各个元素执行 x.lower() 或 x.upper()
match | 根据指定的正则表达式对各个元素执行 re.match
pad | 在字符串的左边、右边或左右两边添加空白符
center | 相当于 pad(side='both')
repeat | 重复值。例如,s.str.repeat(3) 相当于对各个字符串执行 x*3
replace | 用指定字符串替换找到的模式
slice | 对 Series 中的各个字符串进行子串截取
split | 根据分隔符或正则表达式对字符串进行拆分
strip、rstrip、Istrip | 去除空白符,包括换行符。相当于对各个元素执行 x.strip()、x.rstrip(),x.lstrip()