count the number of groups of consecutive digits in a series of strings
<p>consider the <code>pd.Series</code> <code>s</code></p>

<pre><code>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
</code></pre>

<hr>

<p>I'm looking to count the number of groups of consecutive digits in each element of <code>s</code>.  Or, how many integers are in each string.</p>

<p>I'd expec the result to look like</p>

<pre><code>0    2
1    3
2    5
3    6
4    2
5    3
6    5
7    3
8    4
9    4
dtype: int64
</code></pre>

<p>I'm looking for efficiency, though elegance is important too.</p>

<p><strong>UPDATE:</strong> the idea is first to replace all consecutive groups of digist with single <code>1</code> and then delete everything which is not <code>1</code> and finally get the length of the changed string:</p>

<pre><code>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
</code></pre>

<p>Timing against 100K Series:</p>

<pre><code>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,)
</code></pre>

<p>Timing against 1M Series:</p>

<pre><code>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,)
</code></pre>

<p>Explanation:</p>

<pre><code>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
</code></pre>

<p><strong>OLD (slow) answer:</strong></p>

<p>What about using <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.str.extractall.html" rel="nofollow">.str.extractall()</a> in conjunction with <a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.groupby.html" rel="nofollow">.groupby(level=0)</a>?</p>

<pre><code>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
</code></pre>

<p>Explanation:</p>

<pre><code>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
</code></pre>

python pandas