python - 来自生成器的高效 df 插入
问题描述
我正在构建一个数据匹配脚本,它将两个令牌数据集连接起来。代码运行,但有大量记录和标记化字段,需要很长时间才能完成。我正在寻找有关如何提高计算效率的建议。
我会注意到表现不佳的区域,但首先是一些背景:
#example df
d = {'id': [3,6], 'Org_Name': ['Acme Co Inc.', 'Buy Cats Here Inc'], 'Address': ['123 Hammond Lane, Washington, DC', 'Washington, DC 20456']}
left_df = pd.DataFrame(data=d)
# example tokenizer
def tokenize_name(name):
if isinstance(name, basestring) is True:
clean_name = ''.join(c if c.isalnum() else ' ' for c in name)
return clean_name.lower().split()
else:
return name
#tokenizers assigned to columns
left_tokenizers = [
('Org_Name', tokenize_name),
('Address', tokenize_name)
]
#example token dictionary
tokens_dct = {
'acme':1,
'co':1,
'inc':0,
'buy':1,
'cats':1,
'here':1,
'123':1,
'hammond':1,
'lane':0,
'washington':1,
'dc':1,
'20456':1
}
#this is the generator function used to create token/ID pairs
def prepare_join_keys(df, tokenizers):
for source_column, tokenizer in tokenizers:
if source_column in df.columns:
for index, record in enumerate(df[source_column]):
if isinstance(record, numbers.Integral) is False: #control for longs
if isinstance(record, float) is False: #control for nans
for token in tokenizer(record):
if tokens_dct[token] == 1: #tokenize only for tokens present in dictionary with value 1
yield (token, df.iloc[index]['id'])
# THIS CODE TAKES A LONG TIME TO RUN
left_keyed = pd.DataFrame(columns=('token', 'id'))
for item in prepare_join_keys(left_df, left_tokenizers):
left_keyed.loc[len(left_keyed)] = item
left_keyed
字典用于修剪常见的标记(LLC、Corp、www 等),但是对于很多标记,这仍然会在计算上很昂贵。我想知道,我将生成的令牌/ID 对插入数据帧的方式效率低吗?有一个更好的方法吗?还想知道我是否通过使用 if 而不是 elif 来犯下计算罪。
提前致谢。
解决方案
在熊猫中没有真正的理由这样做。使用预建的分词器效率更高。这应该做你想要的。
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np
import pandas as pd
# since you have a predefined vocabulary, you can fix it here
vocabulary = np.array([w for w, b in tokens_dct.items() if b])
cv = CountVectorizer( vocabulary=vocabulary)
frame_list = []
for colname in ['Org_Name', 'Address']:
tokenmapping = cv.fit_transform(left_df[colname])
df_row, token_id = tokenmapping.nonzero()
frame_list.append(pd.DataFrame(np.vstack([vocabulary[token_id], left_df['id'].values[df_row]]).T, columns = ['token', 'id']))
left_keyed = pd.concat(frame_list)
推荐阅读
- javascript - 如何一次在d3中设置多个样式属性
- javascript - Cytoscape js 阻止输入标签的 onChange 函数
- python - 如何修复 Tkinter?每个带有 GUI 的代码都会使 mac os 崩溃并重新启动
- python - 即使有些是空的,我是否应该始终完成所有条件?
- asp.net-mvc - 如何在母版页中使用 Html.RenderPartial?
- c# - Razor 页面链接忽略路由参数
- javascript - 单击输入字段一段时间后,AngularJS视图未更新而模型更改更改
- css - CSS:Div 显示设置为阻止,但它们显示内联
- asp.net - 单击+或-btn时如何更新购物车数量而不刷新页面
- python-3.x - 为什么 `open()` 函数需要一个目录?