根据具有预先分配的唯一标识符的数据帧为数据帧行分配唯一标识符

问题描述

我有基于三列分配唯一标识符的数据框,即 [col2,col3,col3]

数据框 1:

col1      col2     col3     col4      col5         unique_id
1         abc       bcv      zxc      www.com        8
2         bcd       qwe      rty      www.@com       12
3         klp       oiu      ytr      www.io         15
4         zxc       qwe      rty      www.com        6

数据预处理后,将导入Dataframe_2,列值与上图相同,但没有unique_id。 Dataframe_2 行必须根据 col2、col3、col4 并参考 Dataframe1 分配唯一标识符。

如果 Dataframe_2 有 Dataframe1 中不存在的新行,则分配新的标识符。

数据框_2:

col1      col2     col3     col4      col5         
1         bcd       qwe      rty      www.@com              
2         zxc       qwe      rty      www.com
3         abc       bcv      zxc      www.com 
4         kph       hir      mat      www.com            

预期数据帧_2:

col1      col2     col3     col4      col5         unique_id        
1         bcd       qwe      rty      www.@com        12     
2         zxc       qwe      rty      www.com         6
3         abc       bcv      zxc      www.com         8 
4         kph       hir      mat      www.com         35

由于 Row4 不存在于 Dataframe1 中,因此分配了一个新的唯一标识符。

解决方法

# assign the old unique_id
df2n = df2.join(df1.set_index(['col2','col3','col4','col5'])[['unique_id']],on=['col2','col5'],how='left')

# assign new unique_id with max df1.unique_id + 1
id_max = df1.unique_id.max() + 1
null_num = df2n['unique_id'].isnull().sum()

cond = df2n['unique_id'].isnull()
df2n.loc[cond,'unique_id'] = range(id_max,id_max + null_num)
df2n['unique_id'] = df2n['unique_id'].astype(int)

print(df2n)

      col1 col2 col3 col4      col5  unique_id
    0     1  bcd  qwe  rty  www.@com         12
    1     2  zxc  qwe  rty   www.com          6
    2     3  abc  bcv  zxc   www.com          8
    3     4  kph  hir  mat   www.com         16
,

首先通过DataFrame.merge添加列unique_id,对于子集中指定的列on进行合并,忽略左连接['col2','col4']参数。对于不匹配的值会创建缺失值,因此使用 Series.isna 来测试它们,np.arange 用于在最大值之后创建新数组并在 DataFrame.loc

中分配它们
df = Dataframe_2.merge(Dataframe_1[['col2','unique_id']],how='left')

mask = df['unique_id'].isna()
maximal = Dataframe_1['unique_id'].max() + 1

df.loc[mask,'unique_id'] = np.arange(maximal,maximal + mask.sum())

df['unique_id'] = df['unique_id'].astype(int)
print (df)
   col1 col2 col3 col4      col5  unique_id
0     1  bcd  qwe  rty  www.@com         12
1     2  zxc  qwe  rty   www.com          6
2     3  abc  bcv  zxc   www.com          8
3     4  kph  hir  mat   www.com         16
,
import math
import random
import pandas as pd
import numpy as np

df3 = pd.merge(df1,df2,'col4'],how='right')

def return_unique_num(df1):
  uniqueIds = list(df1['unique_id'].values)
  unique_num = random.randint(1,len(df1)+1)
  while True:
    if unique_num in uniqueIds:
      unique_num = random.randint(1,len(df1)+1)
    else:
      break
  return unique_num

for i,e in enumerate(df3['unique_id']):
  if math.isnan(e):
    df3.iloc[i,5] = return_unique_num(df1) #replace nan value with unique integer in df3 unique_id column


df3['unique_id'] = df3['unique_id'].astype(int)

df2['unique_id'] = df3['unique_id']

它将根据 df1 的 unique_id 为 df2 分配唯一 ID

输出

col1      col2     col3     col4      col5         unique_id        
1         bcd       qwe      rty      www.@com        12     
2         zxc       qwe      rty      www.com         6
3         abc       bcv      zxc      www.com         8 
4         kph       hir      mat      www.com         35