それぞれが複数のエントリを持つさまざまな一意の個人のデータセットを取得し、各個人にすべてのエントリの一意の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、というようにしたいです。
だから、私はすでに1つの解決策を持っています、それは2つの値(idに1つ、インデックスに1つ)を繰り返し、前の個体と一致するかどうかに基づいて個体にIDを割り当てる完全なpythonループです:
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を潜在的なソリューションとして検討してきましたが、まだ適切なソリューションを見つけることができていません。ありがとう!
姓と名を結合し、カテゴリに変換してからコードを取得できます。
もちろん、同じ名前の複数の人は同じ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
このアプローチでは、.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
_
タイミングを確認しましたが、この例の小さなデータセットの場合、Alexanderの答えは高速です。
_%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名のデータフレームを作成しました。
_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
_
データセットで両方のアプローチをテストして、データのサイズを考慮してどちらが最適に機能するかを判断することができます。
このメソッドにより、「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