【问题标题】:Efficient df insertion from generator来自生成器的高效 df 插入
【发布时间】:2019-02-06 15:56:58
【问题描述】:

我正在构建一个数据匹配脚本,它将两个数据集连接到令牌上。代码运行,但有大量记录和标记化字段,需要很长时间才能完成。我正在寻找有关如何提高计算效率的建议。

我会注意表现不佳的区域,但首先是一些背景:

#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 犯了计算罪。

提前致谢。

【问题讨论】:

  • 是的,效率极低。
  • 遍历数据框中的项目会很慢。
  • 你最好遍历一个列表,然后使用df
  • 你能提供一个简短的例子吗?
  • 我已经用一些示例 df 和令牌字典更新了代码,现在您应该可以运行代码了。感谢到目前为止的 cmets;听起来我使用 df 的方法可能是罪魁祸首。但是你的意思是源数据需要拆分成列表,或者我插入 df 的方式是为什么这很耗时?

标签: python pandas token generator


【解决方案1】:

在 pandas 中没有真正的理由这样做。使用预建的分词器效率更高。这应该可以满足您的需求。

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)

【讨论】:

  • 谢谢,这让我找到了正确的方向。一个问题,除了“if b == 1”之外,我尝试了此代码以及相同的代码,并且没有观察到行为差异。为什么会这样?
猜你喜欢
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-14
  • 1970-01-01
相关资源
最近更新 更多