# Pandas 处理文本字符串
序列和索引包含一些列的字符操作方法,这可以使我们轻易操作数组中的各个元素。最重要的是,这些方法可以自动跳过 缺失/NA 值。这些方法可以在str属性中访问到,并且基本上和python内建的(标量)字符串方法同名:
In [1]: s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])
In [2]: s.str.lower()
Out[2]:
0 a
1 b
2 c
3 aaba
4 baca
5 NaN
6 caba
7 dog
8 cat
dtype: object
In [3]: s.str.upper()
Out[3]:
0 A
1 B
2 C
3 AABA
4 BACA
5 NaN
6 CABA
7 DOG
8 CAT
dtype: object
In [4]: s.str.len()
Out[4]:
0 1.0
1 1.0
2 1.0
3 4.0
4 4.0
5 NaN
6 4.0
7 3.0
8 3.0
dtype: float64
In [5]: idx = pd.Index([' jack', 'jill ', ' jesse ', 'frank'])
In [6]: idx.str.strip()
Out[6]: Index(['jack', 'jill', 'jesse', 'frank'], dtype='object')
In [7]: idx.str.lstrip()
Out[7]: Index(['jack', 'jill ', 'jesse ', 'frank'], dtype='object')
In [8]: idx.str.rstrip()
Out[8]: Index([' jack', 'jill', ' jesse', 'frank'], dtype='object')
索引的字符串方法在清理或者转换数据表列的时候非常有用。例如,你的列中或许会包含首位的白空格:
In [9]: df = pd.DataFrame(np.random.randn(3, 2),
...: columns=[' Column A ', ' Column B '], index=range(3))
...:
In [10]: df
Out[10]:
Column A Column B
0 0.469112 -0.282863
1 -1.509059 -1.135632
2 1.212112 -0.173215
Since df.columns is an Index object, we can use the .str accessor
In [11]: df.columns.str.strip()
Out[11]: Index(['Column A', 'Column B'], dtype='object')
In [12]: df.columns.str.lower()
Out[12]: Index([' column a ', ' column b '], dtype='object')
这些字符串方法可以被用来清理需要的列。这里,我们想清理开头和结尾的白空格,将所有的名称都换为小写,并且将其余的空格都替换为下划线:
In [13]: df.columns = df.columns.str.strip().str.lower().str.replace(' ', '_')
In [14]: df
Out[14]:
column_a column_b
0 0.469112 -0.282863
1 -1.509059 -1.135632
2 1.212112 -0.173215
小贴士
如果你有一个序列,里面有很多重复的值
(即,序列中唯一元素的数量远小于序列的长度),将原有序列转换为一种分类类型,然后使用.str. 或者 .dt.方法,则会获得更快的速度。
速度的差异来源于,在分类类型的序列中,字符操作只是在categories中完成的,而不是针对序列中的每一个元素。
请注意,相比于字符串类型的序列,带.categories类型的 分类 类别的 序列有一些限制(例如,你不能像其中的元素追加其他的字串:s + " " + s 将不能正确工作,如果s是一个分类类型的序列。并且,.str 中,那些可以对 列表(list) 类型的元素进行操作的方法,在分类序列中也无法使用。
警告
v.0.25.0版以前, .str访问器只会进行最基本的类型检查。
从v.0.25.0起,序列的类型会被自动推断出来,并且会更为激进地使用恰当的类型。
一般来说 .str 访问器只倾向于针对字符串类型工作。只有在个别的情况下,才能对非字符串类型工作,但是这也将会在未来的版本中被逐步修正
# 拆分和替换字符串
类似split的方法返回一个列表类型的序列:
In [15]: s2 = pd.Series(['a_b_c', 'c_d_e', np.nan, 'f_g_h'])
In [16]: s2.str.split('_')
Out[16]:
0 [a, b, c]
1 [c, d, e]
2 NaN
3 [f, g, h]
dtype: object
切分后的列表中的元素可以通过 get 方法或者 [] 方法进行读取:
In [17]: s2.str.split('_').str.get(1)
Out[17]:
0 b
1 d
2 NaN
3 g
dtype: object
In [18]: s2.str.split('_').str[1]
Out[18]:
0 b
1 d
2 NaN
3 g
dtype: object
使用expand方法可以轻易地将这种返回展开为一个数据表.
In [19]: s2.str.split('_', expand=True)
Out[19]:
0 1 2
0 a b c
1 c d e
2 NaN NaN NaN
3 f g h
同样,我们也可以限制切分的次数:
In [20]: s2.str.split('_', expand=True, n=1)
Out[20]:
0 1
0 a b_c
1 c d_e
2 NaN NaN
3 f g_h
rsplit与split相似,不同的是,这个切分的方向是反的。即,从字串的尾端向首段切分:
In [21]: s2.str.rsplit('_', expand=True, n=1)
Out[21]:
0 1
0 a_b c
1 c_d e
2 NaN NaN
3 f_g h
replace 方法默认使用 正则表达式:
In [22]: s3 = pd.Series(