2015-11-16 71 views
1

我正在尝试创建一个NEW_ID列,其中每个完全匹配的值为FIRST_NM,LAST_NM为大熊猫数据框中两列的每次完全匹配创建一个随机数列。

data = np.array([['John', 'Smith', 1], ['John', 'West', 7], ['Eric', 'Adams', 9], 
       ['Jane', 'Doe', 14], ['Jane', 'Doe', 16], ['John', 'Smith', 19]]) 

df = pd.DataFrame(data, columns=['FIRST_NM', 'LAST_NM', 'PAGE_NUM']) 

    FIRST_NM LAST_NM PAGE_NUM 
0  John Smith  1 
1  John West  7 
2  Eric Adams  9 
3  Jane  Doe  14 
4  Jane  Doe  16 
5  John Smith  19 

所需的数据框:

FIRST_NM LAST_NM PAGE_NUM NEW_ID 
0  John Smith  1  654 
1  John West  7  123 
2  Eric Adams  9  78 
3  Jane  Doe  14  3 
4  Jane  Doe  16  3 
5  John Smith  19  654 

我想我应该做类似下面的代码,但我知道这是不对的......

import random 
df.groupby(['FIRST_NM', 'LAST_NM']).apply(lambda group: random.getrandbits(16)) 
+0

你是否考虑过使用一些好的散列函数? –

+0

@SeverinPappadeux听起来像这可能是一个好主意。你能举一个例子吗? – blahblahblah

+0

当然,请参阅答案 –

回答

1

如果使用transform,将广播结果返回到原来的索引你的原始版本将工作:

>>> df["NEW_ID"] = df.groupby(['FIRST_NM', 'LAST_NM']).transform(lambda group: 
    random.getrandbits(16)) 
>>> df 
    FIRST_NM LAST_NM PAGE_NUM NEW_ID 
0  John Smith  1 57757 
1  John Smith  7 57757 
2  Eric Adams  9 46139 
3  Jane  Doe  14 55091 
4  Jane  Doe  16 55091 
5  John Smith  19 57757 

但我不只是采取随机数并希望最好的大风扇(即没有冲突。)如果你有一个像你的榜样一系列类似指标有,你可以使用,而不是:

>>> df.groupby(['FIRST_NM', 'LAST_NM'])["PAGE_NUM"].transform("idxmin") 
0 0 
1 0 
2 2 
3 3 
4 3 
5 0 
dtype: int64 

还是排版本:

>>> df.groupby(['FIRST_NM', 'LAST_NM'])["PAGE_NUM"].transform("idxmin").rank("dense") 
0 1 
1 1 
2 2 
3 3 
4 3 
5 1 
dtype: float64 

一旦你有了这些,你可以安全地将它们映射到唯一的随机数字,不过你喜欢。


不幸的是,我不认为该组的排列是位于有保证,即唯一的地方

>>> grouped = df.groupby(["FIRST_NM", "LAST_NM"]) 
>>> grouped.grouper.group_info[0] 
array([2, 2, 0, 1, 1, 2], dtype=int64) 

我不会介意这顺序返回非此即彼的“秩groupcount()方法首次出现“版本。

0

你并不真的需要使用groupby。你可能推迟作出的字典与映射,然后更好地只使用map指派方式:

nameIDs = {name: ix for name, ix in zip(df.FIRST_NM.unique(), range(df.FIRST_NM.nunique()))} 
df['NEWID'] = df.FIRST_NM.map(nameIDs) 

然后:

>>> df 
    FIRST_NM LAST_NM PAGE_NUM NEWID 
0  John Smith  1  0 
1  John Smith  7  0 
2  Eric Adams  9  1 
3  Jane  Doe  14  2 
4  Jane  Doe  16  2 
5  John Smith  19  0 

在这里,我刚才生成的ID作为连续整数。如果你愿意,你当然可以适应这个使用随机数字,但我真的不明白为什么你会想要。

+0

感谢您的回答。我可能没有提供有关数据的足够信息。并非所有“约翰”的名字都以“史密斯”作为姓。所以我需要一起考虑名字和姓氏,而不仅仅是独特的名字。我将编辑问题中的数据以更好地反映我的问题。 – blahblahblah

1

您可以添加具有良好散列函数的列,或者更快但更不安全(例如下面示例中的cityhash),或者使用加密安全散列或甚至某些基于AES的转换。显然,如果名称相同,则ID将相同。姓氏和名字加入_,你可以使用任何你想要的符号

import numpy as np 
import pandas as pd 
import pyhash 

data = np.array([['John', 'Smith', 1], ['John', 'Smith', 7], ['Eric', 'Adams', 9], 
      ['Jane', 'Doe', 14], ['Jane', 'Doe', 16], ['John', 'Smith', 19]]) 

df = pd.DataFrame(data, columns=['FIRST_NM', 'LAST_NM', 'PAGE_NUM']) 
print(df) 

hasher = pyhash.city_64() 

df['FULL_ID'] = df[['FIRST_NM', 'LAST_NM']].apply(lambda x: hasher('_'.join(x)), axis=1) 
print(df) 
相关问题