(pandas)在顺序无关紧要的情况下,如何基于三列相似的数据创建唯一标识符?

2024-05-12 18:35:11 发布

您现在位置:Python中文网/ 问答频道 /正文

(Python/熊猫) 我正在对英国房价数据做一些分析,看房价是否与附近学校的质量有关。我已将最近三所学校的URN(唯一参考号)与每笔房价交易进行了匹配。数据中的URN\ 1、URN\ 2、URN\ 3列

我想在数据上估计一个固定效应模型,其中固定效应基于最近的三所学校。因此,我想为三所学校的每个集群创建一个唯一的ID,并且我希望这不受学校顺序的影响。房产A和房产B应该有相同的ID,尽管学校的顺序不同

Property    URN_1   URN_2   URN_3
A         100053   100052   100054
B         100052   100054   100053

有人知道我如何使用Python创建唯一的集群id吗

我尝试使用.groupby()用下面的代码创建ID,但是当学校的顺序不同时,这会给出不同的集群ID

以下是我尝试过的:

import pandas as pd
URN1=[1,2,3,4,5]
URN2=[5,4,3,2,1]
URN3=[1,2,3,2,1]
lst=['a','b','c','d','e']
df=pd.DataFrame(list(zip(URN1,URN2,URN3)),
columns['URN_1','URN_2','URN_3'],index=lst)
df['clusterid']=df.groupby(['URN_1','URN_2','URN_3']).ngroup()
print(df)

我想让观测值'a'和'e'具有相同的集群id,但是通过这种方法给它们提供了不同的id


Tags: 数据iddf顺序集群效应学校pd
3条回答

如果您的数据不太长,则此操作有效:

# we sort the values of each row
# and turn them to tuples
markers = (df[['URN_1','URN_2','URN_3']]
             .apply(lambda x: tuple(sorted(x.values)), axis=1)
          )

df['clisterid'] = df.groupby(markers).ngroup()

输出:

  Property   URN_1   URN_2   URN_3  clisterid
0        A  100053  100052  100054          0
1        B  100052  100054  100053          0

选项2:因为上述解决方案使用apply,这在某些情况下可能并不理想。这里有一个小的数学技巧:我们知道一个组(a,b,c)是由(a+b+c, a**2+b**2+c**2, abc)唯一定义的(直到一个置换)。所以我们可以计算这些值并按它们分组:

tmp_df = df[['URN_1','URN_2','URN_3']]

s = tmp_df.sum(1)         # sums
sq = (tmp_df**2).sum(1)   # sum of squares
p = tmp_df.prod(1)        # products

# groupby
df['clisterid'] = df.groupby([s,sq,p]).ngroup()

性能:第一种方法需要14秒来处理200万行,而第二种方法不到1秒

您可以使用已排序的3个骨灰盒为每个骨灰盒创建一个字符串。
然后按这个新变量分组,并像以前一样使用ngroup()

df['URN_join'] = df[['URN_1','URN_2','URN_3']].apply(lambda x: '_'.join([str(nb) for nb in sorted(x)]), axis=1)
df['clusterid'] = df.groupby(['URN_join']).ngroup()
df

输出:

    URN_1   URN_2   URN_3   clusterid   URN_join
a   1       5       1       0           1_1_5
b   2       4       2       1           2_2_4
c   3       3       3       2           3_3_3
d   4       2       2       1           2_2_4
e   5       1       1       0           1_1_5

对组合中唯一的类似字符串的对象使用factorize。既然顺序无关紧要,我们就先把它分类合并

df['clusterid'] = pd.factorize(df[['URN_1','URN_2','URN_3']].apply(lambda x: ','.join([str(y) for y in sorted(x)]),1))[0]

输出:

       URN_1  URN_2  URN_3  clusterid  clisterid
a      1      5      1          0          0
b      2      4      2          1          1
c      3      3      3          2          2
d      4      2      2          3          1
e      5      1      1          4          0

相关问题 更多 >