Python 一种确定两系列码之间一致编码的算法

Python 一种确定两系列码之间一致编码的算法,python,pandas,algorithm,cluster-analysis,data-science,Python,Pandas,Algorithm,Cluster Analysis,Data Science,我遇到一个问题,我试图使用人行横道将数据集中的代码a与代码B相匹配。例如,这些可能是1990年和1991年的行业代码,人口普查改变了他们对行业的编码方式。如果我可以创建一个协调代码,我可以使用该代码来跟踪相同的行业(或新的行业组,如果必要的话)。它们提供了一条人行横道,如下所示: 将熊猫作为pd导入 将numpy作为np导入 df=pd.DataFrame([ [0,0], [1,2], [1,3], [2,4], [3,4], [4,5], [4,6], [5,5], [10,11], [10

我遇到一个问题,我试图使用人行横道将数据集中的代码
a
与代码
B
相匹配。例如,这些可能是1990年和1991年的行业代码,人口普查改变了他们对行业的编码方式。如果我可以创建一个协调代码,我可以使用该代码来跟踪相同的行业(或新的行业组,如果必要的话)。它们提供了一条人行横道,如下所示:

将熊猫作为pd导入
将numpy作为np导入
df=pd.DataFrame([
[0,0],
[1,2],
[1,3],
[2,4],
[3,4],
[4,5],
[4,6],
[5,5],
[10,11],
[10,13],
[11,11]
],columns=list('AB'))
df
A B
0    0   0
1    1   2
2    1   3
3    2   4
4    3   4
5    4   5
6    4   6
7    5   5
8   10  11
9   10  13
10  11  11
因此,我想要的输出将是一个新列,它定义了
a
B
中的非重叠代码。例如,考虑下面的预期结果:

abc
0    0   0  0.0
1    1   2  1.0
2    1   3  1.0
3    2   4  2.0
4    3   4  2.0
5    4   5  3.0
6    4   6  3.0
7    5   5  3.0
8   10  11  4.0
9   10  13  4.0
10  11  11  4.0
我已经开始通过先完成简单的部分来回答这个问题。这些是(一对多)
1:m
和(多对一)
m:1
匹配,我可以简单地分配一个公共值

sizesA=df.groupby('A').size()
sizeb=df.groupby('B').size()
df['sizeA']=df['A'].地图(sizesA)
df['sizeB']=df['B'].map(sizeB)
df['C']=np.nan
next_v=0
#1:m匹配
对于df[df.sizeA>=1]中的a.unique():
如果df[df.A==A]['sizeB'].max()==1:
df['C']=np.其中(df['A']==A,next_v,df['C']))
下一个_v+=1
#m:1匹配
对于df[df.sizeB>1].b.unique()中的b:
如果df[df.B==B]['sizeA'].max()==1:
df['C']=np.其中(df['B']==B,next_v,df['C']))
下一个_v+=1
df
A B尺寸A尺寸B C
0    0   0      1      1  0.0
1    1   2      2      1  1.0
2    1   3      2      1  1.0
3    2   4      1      2  2.0
4    3   4      1      2  2.0
5452Nan
64621Nan
75112Nan
810112NAN
9 10 13 2 1南
1011112南
问题在于(多对多)
m:m
匹配。我似乎想不出一个好办法来解决这个问题,我猜这是一个计算上很难解决的问题。请注意,我可以只在单个代码上分配剩余的值,但这将忽略一个事实,即我可以将它们划分为两个不同的代码,并且仍然保持一致性


另外,如果您对标题有任何建议,请告诉我

C需要从0开始还是可以从1开始?我只是减去1,这样你就可以从0开始。你可以根据自己的需要调整它

使用cumcount和cumsum应该会更容易

df['C'] = ((df.groupby('A').cumcount()==0) & (df.groupby('B').cumcount()==0)).cumsum()-1

print(df)

print(df)

     A   B  C
0    0   0  0
1    1   2  1
2    1   3  1
3    2   4  2
4    3   4  2
5    4   5  3
6    4   6  3
7    5   5  3
8   10  11  4
9   10  13  4
10  11  11  4


我真的想出了一个解决办法。也许没那么优雅

ungroup=df['A'].unique().tolist()
new=pd.Series(index=sorted(df['A'].unique())
Bnew=pd.Series(index=sorted(df['B'].unique()))
g=0
Avals=[未分组的[0]]
尽管如此:
Bvals=df[df['A'].isin(Avals)].B.unique().tolist()
Acheck=df[df['B'].isin(Bvals)].A.unique().tolist()
如果设置(Acheck)=设置(Avals):
重新定位[Avals]=g
b新位置[Bvals]=g
g+=1
ungrouped=[如果a不在Avals中,则a表示在ungrouped中的a]
如果len(未分组)=0:
打破
Avals=[未分组的[0]]
其他:
阿瓦拉斯=阿切克
df['C']=df['A'].map(新)
df
A、B、C
0    0   0  0.0
1    1   2  1.0
2    1   3  1.0
3    2   4  2.0
4    3   4  2.0
5    4   5  3.0
6    4   6  3.0
7    5   5  3.0
8   10  11  4.0
9   10  13  4.0
10  11  11  4.0

当我在更大的人行横道上运行时,这似乎对我不起作用。我需要一些时间来更好地解释为什么/在什么情况下它会失败。但无论如何,我想我找到了一个有效的算法。我也会发布的。但如果一条线有效,那就太好了。不用担心,我很高兴你找到了一个有效的解决方案。我很好奇,它跑到哪里去了,我想知道我是否误解了这个要求。