如何根据非常大的 df 中的名称有效地将唯一 ID 分配给具有多个条目的个人

新手上路,请多包涵

我想获取一个包含一堆不同的唯一个体的数据集,每个个体都有多个条目,并为每个人的所有条目分配一个唯一的 ID。这是 df 的示例:

       FirstName LastName  id
0     Tom       Jones     1
1     Tom       Jones     1
2     David     Smith     1
3     Alex      Thompson  1
4     Alex      Thompson  1

所以,基本上我希望 Tom Jones 的所有条目都具有 id=1,David Smith 的所有条目都具有 id=2,Alex Thompson 的所有条目都具有 id=3,等等。

所以我已经有了一个解决方案,这是一个非常简单的 python 循环,它迭代两个值(一个用于 id,一个用于索引)并根据它们是否与前一个个体匹配来为个体分配一个 id:

 x = 1
i = 1

while i < len(df_test):
    if (df_test.LastName[i] == df_test.LastName[i-1]) &
    (df_test.FirstName[i] == df_test.FirstName[i-1]):
        df_test.loc[i, 'id'] = x
        i = i+1
    else:
        x = x+1
        df_test.loc[i, 'id'] = x
        i = i+1

我遇到的问题是 DataFrame 有大约 900 万个条目,因此使用该循环将花费大量时间来运行。谁能想到一种更有效的方法来做到这一点?我一直在寻找 groupby 和 multiindexing 作为潜在的解决方案,但还没有找到正确的解决方案。

原文由 Simon Sharp 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 357
2 个回答

您可以加入姓氏和名字,将其转换为类别,然后获取代码。

当然,多个同名的人会有相同的 id

 df = df.assign(id=(df['LastName'] + '_' + df['FirstName']).astype('category').cat.codes)
>>> df
  FirstName  LastName  id
0       Tom     Jones   0
1       Tom     Jones   0
2     David     Smith   1
3      Alex  Thompson   2
4      Alex  Thompson   2

原文由 Alexander 发布,翻译遵循 CC BY-SA 3.0 许可协议

此方法使用 .groupby().ngroup() (Pandas 0.20.2 中的新增功能)创建 id :50-column

 df['id'] = df.groupby(['LastName','FirstName']).ngroup()
>>> df

   First    Second  id
0    Tom     Jones   0
1    Tom     Jones   0
2  David     Smith   1
3   Alex  Thompson   2
4   Alex  Thompson   2

我检查了时间,对于这个例子中的小数据集,Alexander 的回答更快:

 %timeit df.assign(id=(df['LastName'] + '_' + df['FirstName']).astype('category').cat.codes)
1000 loops, best of 3: 848 µs per loop

%timeit df.assign(id=df.groupby(['LastName','FirstName']).ngroup())
1000 loops, best of 3: 1.22 ms per loop

然而,对于更大的数据帧, groupby() 方法似乎更快。为了创建一个大型的、有代表性的数据集,我使用了 faker 创建了一个包含 5000 个名字的数据框,然后将前 2000 个名字连接到这个数据框以创建一个包含 7000 个名字的数据框,其中 2000 个是重复的。

 import faker
fakenames = faker.Faker()
first = [ fakenames.first_name() for _ in range(5000) ]
last = [ fakenames.last_name() for _ in range(5000) ]
df2 = pd.DataFrame({'FirstName':first, 'LastName':last})
df2 = pd.concat([df2, df2.iloc[:2000]])

在这个更大的数据集上运行时间给出:

 %timeit df2.assign(id=(df2['LastName'] + '_' + df2['FirstName']).astype('category').cat.codes)
100 loops, best of 3: 5.22 ms per loop

%timeit df2.assign(id=df2.groupby(['LastName','FirstName']).ngroup())
100 loops, best of 3: 3.1 ms per loop

您可能希望在您的数据集上测试这两种方法,以确定在给定数据大小的情况下哪种方法效果最好。

原文由 Craig 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏