質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.40%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

3回答

642閲覧

【python】【pandas】任意条件をもとにダミーデータ列を作成する方法

sanfuji

総合スコア6

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2024/07/02 05:34

実現したいこと

以下の【df】の「id」から、【任意条件】をもとに、ユニークのダミーデータを割り当てた「uniqueid」列を作成したく、その方法を色々と検索し試みたのですが、うまくいかず、行き詰っています。
知見のある方、ご教示いただけないでしょうか。

【任意条件】
「居住地」「勤務地」の値が日(=day列:15-17)をまたいでも、それぞれ同一の場合、異なる「id」を同一人物とみなし、
「uniqueid」にユニークのダミー値を割り当てる

【ダミーデータ】
適当な文字列

【df】
id  |  居住地  |  勤務地  |  day  |
aa1    111111    112233    15
aa2    111112    112231    15
aa3    111113    112232    15
aa4    111114    112234    15
aa5    111115    112235    15
aa6    111116    112236    15
bb1    111111    112233    16
bb3    111113    112232    16
bb5    111115    112235    16
bb6    111116    112236    16
cc1    111111    112233    17
cc3    111113    112232    17
cc5    111115    112235    17

【実現したいこと】
id  |  居住地  |  勤務地  |  day  |  uniqueid  |
aa1    111111    112233    15     aabbcc1
bb1    111111    112233    16     aabbcc1
cc1    111111    112233    17     aabbcc1
aa2    111112    112231    15     aaaa222
aa3    111113    112232    15     aabbcc3
bb3    111113    112232    16     aabbcc3
cc3    111113    112232    17     aabbcc3
aa4    111114    112234    15     aaaa444
aa5    111115    112235    15     aabbcc5
bb5    111115    112235    16     aabbcc5
cc5    111115    112235    17     aabbcc5
aa6    111116    112236    15     aaabbb6
bb6    111116    112236    16     aaabbb6

発生している問題・分からないこと

条件指定におけるダミーデータの付与

該当のソースコード

特になし

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

df = df.groupby(by=["居住地","勤務地","day","id"]).reset_index()

【結果】
id  |  居住地  |  勤務地  |  day  |
aa1    111111    112233    15
aa2    111112    112231    15
aa3    111113    112232    15
aa4    111114    112234    15
aa5    111115    112235    15
aa6    111116    112236    15
bb1    111111    112233    16
bb3    111113    112232    16
bb5    111115    112235    16
bb6    111116    112236    16
cc1    111111    112233    17
cc3    111113    112232    17
cc5    111115    112235    17

補足

【実現したいこと】
id  |  居住地  |  勤務地  |  day  |  uniqueid  |
aa1    111111    112233    15     aabbcc1
bb1    111111    112233    16     aabbcc1
cc1    111111    112233    17     aabbcc1
→aa1,bb1,cc1は、日をまたいでも(day:15-17)「居住地」「勤務地」が同一なので、同一人物とみなし、aabbcc1をユニーク値として付与。
aa2    111112    112231    15     aaaa222
→aa2は、このデータのみのため、、aaaa22をユニーク値として付与。
aa3    111113    112232    15     aabbcc3
bb3    111113    112232    16     aabbcc3
cc3    111113    112232    17     aabbcc3
aa4    111114    112234    15     aaaa444
aa5    111115    112235    15     aabbcc5
bb5    111115    112235    16     aabbcc5
cc5    111115    112235    17     aabbcc5
aa6    111116    112236    15     aaabbb6
bb6    111116    112236    16     aaabbb6
→aa6,bb6は、日をまたいでも(day:15,16)「居住地」「勤務地」が同一なので、同一人物とみなし、aaabbb6をユニーク値として付与。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sanfuji

2024/07/02 06:38

回答ありがとうございます。 【実現したいこと】の補足をします。 【df】は数十万レコードあり、日をまたいでも「居住地」「勤務地」が同一のidは複数あります。 【実現したいこと】 id  |  居住地  |  勤務地  |  day  |  uniqueid  | aa1    111111    112233    15    abc123 bb2    111111    112233    16    abc123 cc3    111111    112233    17    abc123 bb5    111111    112233    16    bbb555 aa7    111111    112233    15    aabb78 bb8    111111    112233    16    aabb78 →「id」がaa1-cc3、bb5、aa7-bb8は、異なるユニークidとしてダミーを割り当てたいのですが、ご教示いただけないでしょうか。
TakaiY

2024/07/02 07:36

上記のように分類するための条件が不明です。 たとえば、aa1 が bb8でなく、bb2 と同一と判断できる理由は何ですか?
sanfuji

2024/07/02 08:53

コメントありがとうございます。 説明不足で恐縮ですが、「id」列は重要ではなく、 「uniqueid」列のダミーデータを作成するにあたり、 「居住地」「勤務地」がそれぞれ同一で、 「day」の番号を15,16,17,15,16,17・・・15,16,17と、 連続させて(15,16 or 16,17 or 15のみ or 16のみ or 17のみも含め)、 このような条件と並びのデータに対して、 ダミーのユニークidを「uniqueid」に割り当てることをしたく、 ご教示いただけないでしょうか。 【実現したいこと】※id列を除いた極端な例   居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    abc123   111111    112233    16    abc123   111111    112233    17    abc123   111111    112233    16    bbb555   111111    112233    15    aabb78   111111    112233    16    aabb78 【実現したいことの補足】 「uniqueid」にダミーデータを割り当てる際の処理は、以下の条件のパターン①から④を順に割り当てるのかと思います。 条件のパターン① 「居住地」「勤務地」が同一で「day」が15-17まで連続する場合   居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    abc123   111111    112233    16    abc123   111111    112233    17    abc123   111111    112233    15    abc234   111111    112233    16    abc234   111111    112233    17    abc234 条件のパターン② 「居住地」「勤務地」が同一で「day」が15,16と連続する場合   居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    efg123   111111    112233    16    efg123   111111    112233    15    efg234   111111    112233    16    efg234 条件のパターン③ 「居住地」「勤務地」が同一で「day」が16,17と連続する場合   居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    16    hij123   111111    112233    17    hij123   111111    112233    16    hij234   111111    112233    17    hij234 条件のパターン④ 「居住地」「勤務地」が同一で「day」が15,16,17それぞれのみの場合   居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    kwe123   111111    112233    16    lqo123   111111    112233    17    axs234 伝え方が下手で恐縮ですが、知見ございましたら、ご教示願います。
TakaiY

2024/07/02 09:13

ということは行の並び順が重要ということですね。   111111    112233    15   111111    998877    15   111111    112233    16 この場合、1行目と3行目は(2行目は当然として)別UniqIDとなるということですね。
sanfuji

2024/07/02 11:28

TakaiYさん、コメントありがとうございます。 おっしゃる通りです。
sanfuji

2024/07/02 11:36

meilanさん、回答ありがとうございます。 記載いただいたコードを実行しますと、以下のエラーが出ます。 エラー原因を調べたのですが、わからず、対応をご教示いただけないでしょうか。 ーー df = df.groupby(['居住地', '勤務地'])\ .apply(lambda x: x.assign(uniqueid=uuid4()), include_groups=False)\ .reset_index()[[*df.columns]+['uniqueid']] ーー TypeError:<lambda>() got an unexpected keyword argument 'include_groups'
melian

2024/07/02 13:08 編集

回答に追記しましたので、そちらをご覧ください。
sanfuji

2024/07/03 01:19

melianさん、コメントと回答ありがとうございます。 ご指摘のとおり、pandas 1.3.2とバージョンが古く、また、明記せず失礼いたしました。 記載いただいたコードの出力結果は以下の通りで、 uniqueidの"abc123"を3つのユニークid(e.g."abc123","ret437","los998")に分けるのが、 【実現したいこと】になります。(補足は15:38,17:53のコメントになります) ご教示いただけないでしょうか。 【出力結果】  居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    abc123   111111    112233    15    abc123   111111    112233    15    abc123   111111    112233    16    abc123   111111    112233    16    abc123   111111    112233    16    abc123   111111    112233    17    abc123   111111    112233    17    abc123   111111    112233    17    abc123              ・              ・   111111    112244    15    efg123   111111    112244    15    efg123   111111    112244    15    efg123   111111    112244    16    efg123   111111    112244    16    efg123   111111    112244    16    efg123   111111    112244    17    efg123   111111    112244    17    efg123   111111    112244    17    efg123 【実現したいこと】  居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    abc123   111111    112233    16    abc123   111111    112233    17    abc123   111111    112233    15    abc456   111111    112233    16    abc456   111111    112233    17    abc456   111111    112233    15    abc789   111111    112233    16    abc789   111111    112233    17    abc789              ・              ・   111111    112244    15    efg123   111111    112244    16    efg123   111111    112244    17    efg123   111111    112244    15    efg456   111111    112244    16    efg456   111111    112244    17    efg456   111111    112244    15    efg789   111111    112244    16    efg789   111111    112244    17    efg789 →15,16,17を繰り返す並びのデータ(17:53のコメントの条件含め)にユニークidをダミーで付与したく、ご教示願います。
sanfuji

2024/07/03 01:35

badfanさん、回答ありがとうございます。 説明がうまくできず恐縮です。 記載いただいたコードの出力結果は以下の通りで、dayが変わるところだけでなく、 dayが連続しているデータにユニークidを割り当てるのが、【実現したいこと】になります。 ご教示いただけないでしょうか。 【出力結果】  居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    abc123   111111    112233    15    abc234   111111    112233    15    abc345   111111    112233    16    abc345   111111    112233    16    abc567   111111    112233    16    abc789   111111    112233    17    abc789   111111    112233    17    abc890   111111    112233    17    abc90a 【実現したいこと】  居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    abc123   111111    112233    16    abc123   111111    112233    17    abc123   111111    112233    15    abc456   111111    112233    16    abc456   111111    112233    17    abc456   111111    112233    15    abc789   111111    112233    16    abc789   111111    112233    17    abc789
sanfuji

2024/07/03 02:21

コメントと回答いただきました皆さん、【実現したいこと】の説明が不備等、ご容赦ください。 【実現したいこと】の別の言い方になります。 以下の【df】のデータを上からなめていき、 「居住地」「勤務地」がそれぞれ同一で、「day」が15のデータに”abc123”のダミーデータを「uniqueid」列に割り当てます。 次に、「居住地」「勤務地」がそれぞれ同一で、「day」が16のデータがあれば、"abc123"を付与し、 次に、「居住地」「勤務地」がそれぞれ同一で、「day」が17のデータがあれば、"abc123"を付与し、 この"abc123"の割り当ては完了。 次のダミーデータ割り当てに移り、 「居住地」「勤務地」がそれぞれ同一で、「day」が15のデータに”abc456”のダミーデータを「uniqueid」列に割り当て、以降、同じことを繰り返します。 (繰り返す過程で、7/2 17:53のコメントにある「条件のパターン」が生じると思い、記載いたしました。) 【df】   居住地  |  勤務地  |  day  |   111111    112233    15  → "abc123"をダミーデータとして「uniqueid」に付与   111111    112233    15  → "aabbcc"をダミーデータとして「uniqueid」に付与   928845    817264    15  → "abc456"をダミーデータとして「uniqueid」に付与   200980    200121    15  → "abc789"をダミーデータとして「uniqueid」に付与   548192    556119    15  → "efg123"をダミーデータとして「uniqueid」に付与   111111    112233    16  → "abc123"をダミーデータとして「uniqueid」に付与   111111    112233    15  → "aabbcc"をダミーデータとして「uniqueid」に付与   178260    178227    16  → "efg456"をダミーデータとして「uniqueid」に付与   200980    200121    16  → "abc789"をダミーデータとして「uniqueid」に付与   548192    556119    16  → "efg123"をダミーデータとして「uniqueid」に付与   111111    112233    17  → "abc123"をダミーデータとして「uniqueid」に付与   111111    112233    15  → "aabbcc"をダミーデータとして「uniqueid」に付与   178260    178227    17  → "efg456"をダミーデータとして「uniqueid」に付与   333704    333882    17  → "efg789"をダミーデータとして「uniqueid」に付与   548192    556119    17  → "efg123"をダミーデータとして「uniqueid」に付与            ↓   居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    abc123   111111    112233    15    aabbcc   928845    817264    15    abc456   200980    200121    15    abc789   548192    556119    15    efg123   111111    112233    16    abc123   111111    112233    15    aabbcc   178260    178227    16    efg456   200980    200121    16    abc789   548192    556119    16    efg123   111111    112233    17    abc123   111111    112233    15    aabbcc   178260    178227    17    efg456   333704    333882    17    efg789   548192    556119    17    efg123 【実現したいこと】※dayを15,16,17を繰り返す並びにすると   居住地  |  勤務地  |  day  |  uniqueid  |   111111    112233    15    abc123   111111    112233    16    abc123   111111    112233    17    abc123   111111    112233    15    aabbcc   111111    112233    16    aabbcc   111111    112233    17    aabbcc   928845    817264    15    abc456   200980    200121    15    abc789   200980    200121    16    abc789   548192    556119    15    efg123   548192    556119    16    efg123   548192    556119    17    efg123   178260    178227    16    efg456   178260    178227    17    efg456   333704    333882    17    efg789
melian

2024/07/03 03:11

7行目の day が 15 となっていますが、これは 16 ではないでしょうか? 111111    112233    15  → "aabbcc"をダミーデータとして「uniqueid」に付与 また、12行目の day は 17 ではないでしょうか? 111111    112233    15  → "aabbcc"をダミーデータとして「uniqueid」に付与
sanfuji

2024/07/03 04:51

melianさん、ご指摘ありがとうございます。 おっしゃる通り、7行目のdayは 16 、12行目は 17 です。失礼いたしました。
TakaiY

2024/07/03 06:41

dayは15, 16, 17 しかないのでしょうか? 任意の値になりますか? 元のデータはどのように並んでいますか? 居住地・勤務地が同じで、dayも同じなデータは存在する可能性はありますか? 存在する場合、どのように扱いますか。 3つ前のポストで、一番最初の手順に > 「居住地」「勤務地」がそれぞれ同一で、「day」が15のデータに”abc123”のダミーデータを「uniqueid」列に割り当てます。 と書いてあります。 この「それぞれ」同一とは何がそれぞれ同一なのでしょうか? 単に「最初にみつかったdayが15のデータ」ではないのでしょうか?
sanfuji

2024/07/03 06:55

TakaiYさん、コメントありがとうございます。 他の方の回答により、本件、解決とさせていただきます。 説明等の不備、ご容赦ください。
guest

回答3

0

ベストアンサー

追記の追記

コメントにて、並べ替えの方法が提示されましたが、想定している並べ替え方と違うため、下記回答ではできないケースがあるかもしれません。

追記

もとのdfがちゃんと並んでいるわけではなく、こちらで整列の方法も考える必要があるみたいです。できるだけ連番ができるようにしてみました。

python

1df['n'] = df.groupby(['居住地', '勤務地', 'day']).cumcount() 2df = df.sort_values(['居住地', '勤務地', 'n', 'day']).drop(columns='n') 3 4consecutive = ((df['居住地'] == df['居住地'].shift(1)) 5 & (df['勤務地'] == df['勤務地'].shift(1)) 6 & (df['day'] - df['day'].shift(1) == 1)) 7 8df['uniqueid'] = (~consecutive).cumsum()

元の回答とは、ソートの方法を変えただけです。(コード省略のため、uniquid は連番のままです)

元の回答

質問やコメントにある、同じ uniqueid を割り振る条件がちょっと曖昧なので、勝手な想像で

  • もとの df を [居住地, 勤務地] で stable なソートをしたデータで、
  • 居住地、勤務地が同じで、day が連番になっているかたまり

に同じuniqueidを割り当てるという考え方でやってみました。

python

1df = df.sort_values(['居住地', '勤務地'], kind='stable') 2 3consecutive = ((df['居住地'] == df['居住地'].shift(1)) 4 & (df['勤務地'] == df['勤務地'].shift(1)) 5 & (df['day'] - df['day'].shift(1) == 1)) 6 7unique_id = (~consecutive).cumsum()

(よくある、ある条件で区切って groupby するときにやってるのと同じ)

このままだと、unique_id が単なる連番なので

python

1df['uniqueid'] = df.groupby(unique_id)['id'].transform('sum')

で元の id の連結にするとか、以下のように map を使ってランダムなもの(ここでは uuid4)で置き換えるといいのではないでしょうか。

python

1from uuid import uuid4 2 3mapper = {uid: str(uuid4()) for uid in unique_id.unique()} 4df['uniqueid'] = unique_id.map(mapper)

投稿2024/07/02 14:16

編集2024/07/03 03:28
bsdfan

総合スコア4716

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sanfuji

2024/07/03 06:49

bsdfanさん、回答ありがとうございます。 編集いただいたコードの実行で、【実現したいこと】の出力を確認いたしました。 説明等の不備で、お手数おかけしましたが、ご容赦ください。
guest

0

python

1import pandas as pd 2import io 3from uuid import uuid4 4 5csv_data = ''' 6居住地,勤務地,day 7111111,112233,15 8111111,112233,15 9928845,817264,15 10200980,200121,15 11548192,556119,15 12111111,112233,16 13111111,112233,16 14178260,178227,16 15200980,200121,16 16548192,556119,16 17111111,112233,17 18111111,112233,17 19178260,178227,17 20333704,333882,17 21548192,556119,17 22''' 23df = pd.read_csv(io.StringIO(csv_data)) 24 25# 26uid_iter = (uuid4() for _ in range(len(df))) 27cols = df.columns.to_list() 28df['cumcount'] = df.groupby(cols).cumcount() 29df['uniqueid'] = df.groupby(['居住地', '勤務地', 'cumcount'], sort=False)['cumcount'].transform(lambda _: next(uid_iter)) 30df = df.set_index('uniqueid').loc[df['uniqueid'].unique()].reset_index()[[*cols, 'uniqueid']] 31 32print(df)

投稿2024/07/02 10:18

編集2024/07/03 07:49
melian

総合スコア20255

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sanfuji

2024/07/03 06:52

melianさん、回答ありがとうございます。 また、処理に関する説明もありがとうございます。勉強いたします。 説明等の不備で、お手数をおかけしましたが、ご容赦ください。
melian

2024/07/03 07:02

結局のところ、この回答では【実現したいこと】の出力にはならなかったのでしょうか?
guest

0

たんに居住地と勤務地を連結したもの、たとえば11111-112233なりを採用すればよいかと思います。

投稿2024/07/02 05:42

can110

総合スコア38337

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.40%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問