编辑(感谢 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倍。但有没有办法更快地完成它(我觉得这个迭代不是最优的)。
答案 0 :(得分:2)
您可以先转换index
to_series
,因为apply
尚未与index
一起使用。上次apply
value_counts
,fillna
并astype
投放到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