使用str.count()在索引

时间:2016-05-30 13:26:36

标签: python pandas count

编辑(感谢 Jezrael 带领我去实现目标):

我有一个电话号码列表,我希望每个数字都可以计算每个数字的出现次数。您了解双重for循环是不可能的,因为我有几十万个电话号码可供计算。

为此我创建了一个数据帧(因为我觉得这可能是一种有效的方法),它在每一行中包含电话号码的分割:

numbers = ['0615260518','0815465948','0215616235','0415291826']
df = pd.DataFrame([list(number) for number in numbers])


Out[1]:
    0   1   2   3   4   5   6   7   8   9
0   0   6   1   5   2   6   0   5   1   8
1   0   8   1   5   4   6   5   9   4   8
2   0   2   1   5   6   1   6   2   3   5
3   0   4   1   5   2   9   1   8   2   6

然后我需要填写所需的计数。期望的输出:

Out[2]:
            0   1   2   3   4   5   6   7   8   9
0615260518  2   2   1   0   0   2   2   0   1   0
0815465948  1   1   0   0   2   2   1   0   2   1
0215616235  1   2   2   1   0   2   2   0   0   0
0415291826  1   2   2   0   1   1   1   0   1   1

这是一种血腥而非pythonic的方式来实现它:

for num in df.index:
    for col in df.columns:
        df.ix[num,col] = num.count(str(col))

计算时间太长,然后Jezrael给了我这个解决方案:

df.apply(lambda x: x.value_counts(), axis=1).fillna(0).astype(int)

哪种方式更好,但仍然太长。所以我试图替换那些不适合小型数据帧的value_counts:

df.apply(lambda x: digit_count(''.join(x)), axis=1)

其中:

def digit_count(number):
    my_string = list(number.lower())
    my_dict = []
    for i in np.arange(10):
        my_dict.append(my_string.count(str(i)))
    return my_dict

大约快3倍。但有没有办法更快地完成它(我觉得这个迭代不是最优的)。

1 个答案:

答案 0 :(得分:2)

您可以先转换index to_series,因为apply尚未与index一起使用。上次apply value_countsfillnaastype投放到int

a = (df.index.to_series().apply(lambda x: pd.Series(list(x))))
print (a)
            0  1  2  3  4  5  6  7  8  9
0615260518  0  6  1  5  2  6  0  5  1  8
0815465948  0  8  1  5  4  6  5  9  4  8
0215616235  0  2  1  5  6  1  6  2  3  5
0415291826  0  4  1  5  2  9  1  8  2  6

print (a.apply(lambda x: x.value_counts(), axis=1).fillna(0).astype(int))

            0  1  2  3  4  5  6  8  9
0615260518  2  2  1  0  0  2  2  1  0
0815465948  1  1  0  0  2  2  1  2  1
0215616235  1  2  2  1  0  2  2  0  0
0415291826  1  2  2  0  1  1  1  1  1

编辑:

from collections import Counter
print (pd.DataFrame([x for x in a.apply(Counter, axis=1)]))
   0  1    2    3    4  5  6    8    9
0  2  2  1.0  NaN  NaN  2  2  1.0  NaN
1  1  1  NaN  NaN  2.0  2  1  2.0  1.0
2  1  2  2.0  1.0  NaN  2  2  NaN  NaN
3  1  2  2.0  NaN  1.0  1  1  1.0  1.0

<强>计时len(df)=4):

In [288]: %timeit (a.apply(lambda x: x.value_counts(), axis=1))
100 loops, best of 3: 3.74 ms per loop

In [289]: %timeit (pd.DataFrame([x for x in a.apply(Counter, axis=1)]))
1000 loops, best of 3: 1.27 ms per loop

len(df)=4k):

In [296]: %timeit (pd.DataFrame([x for x in a.apply(Counter, axis=1)]))
10 loops, best of 3: 87 ms per loop

In [297]: %timeit (a.apply(lambda x: x.value_counts(), axis=1))
1 loop, best of 3: 2.45 s per loop