pandas:按键分组,将乱七八糟的字符串聚类
pandas: grouping by key to cluster messy strings
我有一个 table 看起来像这样:
company_id,company_name
1,Amazon
1,Amazon Ltd
2,Google
1,Amazon
2,Gogle
3,Facebook Ltd
3,Facebook LTD
1,AMAZON
1,AMAZON LTD
2,GOOGLE
3,Facebook
3,Face book
所以我对每个公司都有一个唯一标识符,但它们的文本表示不同。我努力的是消除这些不一致,并有一些类似的东西:
company_id,company_name
1,Amazon
1,Amazon
2,Google
1,Amazon
2,Google
3,Facebook
3,Facebook
1,Amazon
1,Amazon
2,Google
3,Facebook
3,Facebook
我对选择标准并没有死心塌地 - 它可以是所述组中最常见的值,也可以是随机值。但我需要的是高效的东西,因为我的 table 已经增长到包含数百万行。
我的解决方案是创建一个包含 id -> name
的独特组合的散列图,然后根据这些进行替换。大致如下:
dd = df.drop_duplicates().set_index('company_id').to_dict()['company_name']
df.company_name = df.company_id
df.company_name = df.company_name.replace(dd)
它在较小的集合上运行良好,但由于它创建的哈希映射很大,它变得相当慢且内存效率低下。
我也尝试过基于 company_id
的 groupby
并用随机值替换每个组中的所有 company_name
,但我无法修改底层数据框(没有 .loc
ing 它,这是双倍低效的)。
想到的最后一个选项是创建一个具有唯一值的单独框架 (df.drop_duplicates('company_id')
) 并将其与基于 company_id
的原始框架合并,但这听起来并不可怕也有效率。
您可以按 company_id
分组并访问公司 ID:
df.groupby('company_id').first().loc[df.company_id]
结果:
如果您想要作为列,请重置索引:
df.groupby('company_id').first().loc[df.company_id].reset_index()
结果:
我已经使用 map
在相当大的 DataFrame 上测试了您的解决方案,它看起来非常高效:
prng = np.random.RandomState(0)
df = pd.DataFrame({'company_id': prng.randint(10**6, size=10**7),
'company_name': prng.rand(10**7).astype('str')})
# It has 10m unique identifiers each having 10 entries on average
# ranges from 1 to 28.
df.head()
company_id company_name
0 985772 0.4097176168442743
1 305711 0.506659503051052
2 435829 0.45049621797963846
3 117952 0.21756825314220174
4 963395 0.07977409062048224
现在您可以在 company_id
和第一次出现的 company_name
之间为该 ID 创建一个映射器:
%%timeit
mapper = df.drop_duplicates(subset='company_id').set_index('company_id')['company_name']
df['company_id'].map(mapper)
1 loop, best of 3: 1.86 s per loop
由于 ,transform
也是一种可能,尽管我创建的这个特定数据集的性能不如 map:
%timeit df.groupby('company_id')['company_name'].transform('first')
1 loop, best of 3: 2.33 s per loop
.loc
看起来效率很低:
%timeit df.groupby('company_id').first().loc[df.company_id]
1 loop, best of 3: 26.4 s per loop
一般来说,您最好对此类数据使用分类。请参阅另一个讨论 here。
我有一个 table 看起来像这样:
company_id,company_name
1,Amazon
1,Amazon Ltd
2,Google
1,Amazon
2,Gogle
3,Facebook Ltd
3,Facebook LTD
1,AMAZON
1,AMAZON LTD
2,GOOGLE
3,Facebook
3,Face book
所以我对每个公司都有一个唯一标识符,但它们的文本表示不同。我努力的是消除这些不一致,并有一些类似的东西:
company_id,company_name
1,Amazon
1,Amazon
2,Google
1,Amazon
2,Google
3,Facebook
3,Facebook
1,Amazon
1,Amazon
2,Google
3,Facebook
3,Facebook
我对选择标准并没有死心塌地 - 它可以是所述组中最常见的值,也可以是随机值。但我需要的是高效的东西,因为我的 table 已经增长到包含数百万行。
我的解决方案是创建一个包含 id -> name
的独特组合的散列图,然后根据这些进行替换。大致如下:
dd = df.drop_duplicates().set_index('company_id').to_dict()['company_name']
df.company_name = df.company_id
df.company_name = df.company_name.replace(dd)
它在较小的集合上运行良好,但由于它创建的哈希映射很大,它变得相当慢且内存效率低下。
我也尝试过基于 company_id
的 groupby
并用随机值替换每个组中的所有 company_name
,但我无法修改底层数据框(没有 .loc
ing 它,这是双倍低效的)。
想到的最后一个选项是创建一个具有唯一值的单独框架 (df.drop_duplicates('company_id')
) 并将其与基于 company_id
的原始框架合并,但这听起来并不可怕也有效率。
您可以按 company_id
分组并访问公司 ID:
df.groupby('company_id').first().loc[df.company_id]
结果:
如果您想要作为列,请重置索引:
df.groupby('company_id').first().loc[df.company_id].reset_index()
结果:
我已经使用 map
在相当大的 DataFrame 上测试了您的解决方案,它看起来非常高效:
prng = np.random.RandomState(0)
df = pd.DataFrame({'company_id': prng.randint(10**6, size=10**7),
'company_name': prng.rand(10**7).astype('str')})
# It has 10m unique identifiers each having 10 entries on average
# ranges from 1 to 28.
df.head()
company_id company_name
0 985772 0.4097176168442743
1 305711 0.506659503051052
2 435829 0.45049621797963846
3 117952 0.21756825314220174
4 963395 0.07977409062048224
现在您可以在 company_id
和第一次出现的 company_name
之间为该 ID 创建一个映射器:
%%timeit
mapper = df.drop_duplicates(subset='company_id').set_index('company_id')['company_name']
df['company_id'].map(mapper)
1 loop, best of 3: 1.86 s per loop
由于 transform
也是一种可能,尽管我创建的这个特定数据集的性能不如 map:
%timeit df.groupby('company_id')['company_name'].transform('first')
1 loop, best of 3: 2.33 s per loop
.loc
看起来效率很低:
%timeit df.groupby('company_id').first().loc[df.company_id]
1 loop, best of 3: 26.4 s per loop
一般来说,您最好对此类数据使用分类。请参阅另一个讨论 here。