我想要一组数据集,其中包含一堆不同的独特个体,每个人都有多个条目,并为每个人分配一个唯一的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
我遇到的问题是数据框有大约900万个条目,因此使用该循环会花费大量时间来运行。谁能想到更有效的方法呢?我一直在将groupby和multiindexing视为潜在的解决方案,但尚未找到合适的解决方案。谢谢!
答案 0 :(得分:20)
此方法使用.groupby()
和.ngroup()
(Pandas 0.20.2中的新内容)来创建id
列:
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
我检查了时间,对于这个例子中的小数据集,亚历山大的答案更快:
%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
您可能希望在数据集上测试这两种方法,以确定哪种方法在数据大小的情况下效果最佳。
答案 1 :(得分:9)
您可以加入姓氏和名字,将其转换为类别,然后获取代码。
当然,具有相同名称的多个人具有相同的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
答案 2 :(得分:0)
此方法允许使用变量定义“id”列名称。另外,与assign或groupby方法相比,我发现它更容易阅读。
# Create Dataframe
df = pd.DataFrame(
{'FirstName': ['Tom','Tom','David','Alex','Alex'],
'LastName': ['Jones','Jones','Smith','Thompson','Thompson'],
})
newIdName = 'id' # Set new name here.
df[newIdName] = (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