我想在创建df关键字计数(关键字与其他关键字一起出现)时加快嵌套循环的速度



使用Pandas我有一个df,它是14000行乘56列(关键字(我有一个1406项的关键字列表(full_keys(和一个使用关键字列表作为索引和列的空(0(数据帧(称为key_frame((所以1406x1406(

我想遍历df的每一行,对于该行中的每个关键字,增加该关键字与该行中存在的每个其他关键字在key_frame中的交集。

key_frame = pd.DataFrame(columns=full_keys, index=full_keys).fillna(0) # create empty df 
for i, r in keywords.iterrows(): #iterate through each row in df
for index, rows in key_frame.iterrows(): #iterate through blank df to tabulate
if index in list(r): # if the index (which is a keyword) appears in row...
for x in r: #iterate through row and for each intersection loc[index, x] increment tally by 1
key_frame.loc[index, x]+=1

我也有这个,和上面一样,但评论行:

key_frame_2 = pd.DataFrame(columns=full_keys, index=full_keys).fillna(0)
for i, r in keywords.iterrows():
for x in full_keys: #iterate through list rather than key_frame, it's...faster?
if x in list(r):
for keyword in r:
key_frame_2.loc[x, keyword]+=1

感觉生疏,很喜欢一些指针!我知道有更好的方法。

假设keywords数据帧仅包含来自full_keys:的元素

>>> full_keys = ["A", "B", "C", "D", "E"]
>>> keywords
0  1  2
0  B  A  C
1  C  B  D
2  E  C  D
3  A  D  E
4  E  A  D

您可以首先创建一个DataFrame,该DataFrame为关键字中的每一行包含一行,其中包含所有关键字对的列表(包括重复的关键字对和所有排序中的关键字对(。我们使用itertools.product:实现了这一点

import itertools
key_frame = keywords.apply(lambda row: list(itertools.product(row, repeat=2)), axis=1)
>>> key_frame
0    [(B, B), (B, A), (B, C), (A, B), (A, A), (A, C...
1    [(C, C), (C, B), (C, D), (B, C), (B, B), (B, D...
2    [(E, E), (E, C), (E, D), (C, E), (C, C), (C, D...
3    [(A, A), (A, D), (A, E), (D, A), (D, D), (D, E...
4    [(E, E), (E, A), (E, D), (A, E), (A, A), (A, D...
dtype: object

然后,将这些列表压平,得到所有对的序列,并对对进行计数(这基本上为您提供了关键字对的一维直方图(:

key_frame = key_frame.explode().value_counts()
>>> key_frame
(D, D)    4
(A, A)    3
(D, E)    3
...
(C, E)    1
(A, C)    1
(A, B)    1
dtype: int64

现在,为了将其转换为关键字的二维直方图,我们使用unstack(),它要求索引是MultiIndex,而不是元组的索引:

key_frame.index = pd.MultiIndex.from_tuples(key_frame.index)
key_frame = key_frame.unstack()
>>> key_frame
A    B    C    D    E
A  3.0  1.0  1.0  2.0  2.0
B  1.0  2.0  2.0  1.0  NaN
C  1.0  2.0  3.0  2.0  1.0
D  2.0  1.0  2.0  4.0  3.0
E  2.0  NaN  1.0  3.0  3.0

在此阶段,key_frameDataFrame包含所需DataFrame中的所有非零条目。这可能已经足够好了,但为了填充缺失的列、行或NaN条目,我们可以使用reindex()fillna():

key_frame = key_frame.reindex(full_keys, columns=full_keys).fillna(0)
>>> key_frame
A    B    C    D    E
A  3.0  1.0  1.0  2.0  2.0
B  1.0  2.0  2.0  1.0  0.0
C  1.0  2.0  3.0  2.0  1.0
D  2.0  1.0  2.0  4.0  3.0
E  2.0  0.0  1.0  3.0  3.0

这应该会给你一个与使用代码实现的DataFrame相同的DataFrame,但只花了一小部分时间——在相同的keywordsDataFrame(有100行和10列(上运行代码所花费的时间大约是这个解决方案的100倍。

最新更新