考虑pd.Series
s
import pandas as pd
import numpy as np
np.random.seed([3,1415])
p = (.35, .35, .1, .1, .1)
s = pd.DataFrame(np.random.choice(['', 1] + list('abc'), (10, 20), p=p)).sum(1)
s
0 11111bbaacbbca1
1 1bab111aaaaca1a
2 11aaa1b11a11a11
3 1ca11bb1b1a1b1
4 bb1111b1111
5 b1111c1aa111
6 1b1a111b11b1ab
7 1bc111ab1ba
8 a11b1b1b11111
9 1cc1ab1acc1
dtype: object
我想要计算s
每个元素中连续数字组的数量。或者,每个字符串中有多少个整数。
我预计结果看起来像
0 2
1 3
2 5
3 6
4 2
5 3
6 5
7 3
8 4
9 4
dtype: int64
我正在寻找效率,虽然优雅也很重要。
答案 0 :(得分:4)
更新:这个想法首先用单1
替换所有连续的挖掘者组,然后删除不是1
的所有内容,最后得到更改的长度字符串:
In [159]: s.replace(['\d+', '[^1]+'], ['1', ''], regex=True).str.len()
Out[159]:
0 2
1 3
2 5
3 6
4 2
5 3
6 5
7 3
8 4
9 4
dtype: int64
针对100K系列的时间:
In [160]: %timeit big.replace(['\d+', '[^1]+'], ['1', ''], regex=True).str.len()
1 loop, best of 3: 1 s per loop
In [161]: %timeit big.apply(lambda x: len(re.sub('\D+', ' ', x).strip().split()))
1 loop, best of 3: 1.18 s per loop
In [162]: %timeit big.str.replace(r'\D+', ' ').str.strip().str.split().str.len()
1 loop, best of 3: 1.25 s per loop
In [163]: big.shape
Out[163]: (100000,)
针对1M系列的时间:
In [164]: big = pd.concat([s] * 10**5, ignore_index=True)
In [165]: %timeit big.replace(['\d+', '[^1]+'], ['1', ''], regex=True).str.len()
1 loop, best of 3: 9.98 s per loop
In [166]: %timeit big.apply(lambda x: len(re.sub('\D+', ' ', x).strip().split()))
1 loop, best of 3: 11.7 s per loop
In [167]: %timeit big.str.replace(r'\D+', ' ').str.strip().str.split().str.len()
1 loop, best of 3: 12.6 s per loop
In [168]: big.shape
Out[168]: (1000000,)
说明:
In [169]: s.replace(['\d+', '[^1]+'], ['1', ''], regex=True)
Out[169]:
0 11
1 111
2 11111
3 111111
4 11
5 111
6 11111
7 111
8 1111
9 1111
dtype: object
OLD(慢)回答:
如何将.str.extractall()与.groupby(level=0)结合使用呢?
In [130]: s.str.extractall('(\d+)').groupby(level=0).count()
Out[130]:
0
0 2
1 3
2 5
3 6
4 2
5 3
6 5
7 3
8 4
9 4
说明:
In [131]: s.str.extractall('(\d+)')
Out[131]:
0
match
0 0 11111
1 1
1 0 1
1 111
2 1
2 0 11
1 1
2 11
3 11
4 11
3 0 1
1 11
2 1
3 1
4 1
5 1
4 0 1111
1 1111
5 0 1111
1 1
2 111
6 0 1
1 1
2 111
3 11
4 1
7 0 1
1 111
2 1
8 0 11
1 1
2 1
3 11111
9 0 1
1 1
2 1
3 1
答案 1 :(得分:4)
PiRSquared和MaxU解决方案非常棒。
但是,我注意到apply
通常比使用多个字符串方法快一点。
In [142]: %timeit s.apply(lambda x: len(re.sub('\D+', ' ', x).strip().split()))
1 loop, best of 3: 367 ms per loop
In [143]: %timeit s.str.replace(r'\D+', ' ').str.strip().str.split().str.len()
1 loop, best of 3: 403 ms per loop
In [145]: s.shape
Out[145]: (100000L,)
答案 2 :(得分:1)