93171


**実行環境**  
Windows 10  
Python 3.X  
pandas

### データの説明

下記の元データはログをcsv化したものの一部の例になります。  
こちらはid,timestampというカラムで構成されています。  
timestampは昇順で並べられており、それに沿ってidが並べられています。  
idは基本的にはまとまっておりますが、遅延などにより、別のidが先に割り込む形で出力されることがあり、その部分のログとなっております。

### やりたいこと

こちらの元データを下記の **加工したいデータ** のようにsortしたいと考えております。  
同一idはまとめて出力し、そのうえでtimestamp順に出力したいと考えています。  
各idの先頭のtimestampでソートできればと考えております。  
どのようにするとsortが可能でしょうか？

**元データ**

id | timestamp  
---|---  
idefs | 2022-12-15T00:00:01.0000000Z  
idefs | 2022-12-15T00:00:02.0000000Z  
idefs | 2022-12-15T00:00:03.0000000Z  
idefs | 2022-12-15T00:00:04.0000000Z  
aaefsd | 2022-12-15T00:00:05.0000000Z  
idefs | 2022-12-15T00:00:06.0000000Z  
aaefsd | 2022-12-15T00:00:07.0000000Z  
aaefsd | 2022-12-15T00:00:08.0000000Z  
qwerty | 2022-12-15T00:00:09.0000000Z  
aaefsd | 2022-12-15T00:00:10.0000000Z  
aaefsd | 2022-12-15T00:00:11.0000000Z  
qwerty | 2022-12-15T00:00:12.0000000Z  
qwerty | 2022-12-15T00:00:13.0000000Z  
qwerty | 2022-12-15T00:00:14.0000000Z  
qwerty | 2022-12-15T00:00:15.0000000Z  
  
**加工したいデータ**

id | timestamp  
---|---  
idefs | 2022-12-15T00:00:01.0000000Z  
idefs | 2022-12-15T00:00:02.0000000Z  
idefs | 2022-12-15T00:00:03.0000000Z  
idefs | 2022-12-15T00:00:04.0000000Z  
idefs | 2022-12-15T00:00:06.0000000Z  
aaefsd | 2022-12-15T00:00:05.0000000Z  
aaefsd | 2022-12-15T00:00:07.0000000Z  
aaefsd | 2022-12-15T00:00:08.0000000Z  
aaefsd | 2022-12-15T00:00:10.0000000Z  
aaefsd | 2022-12-15T00:00:11.0000000Z  
qwerty | 2022-12-15T00:00:09.0000000Z  
qwerty | 2022-12-15T00:00:12.0000000Z  
qwerty | 2022-12-15T00:00:13.0000000Z  
qwerty | 2022-12-15T00:00:14.0000000Z  
qwerty | 2022-12-15T00:00:15.0000000Z  
  
### 試したこと

sort_valuesを使用しsortを行いました。  
こちらは同じidでデータをまとめ、sortが可能ですが、idも昇順で並び替えてしまうため、  
原則timestamp順で並び替えることができませんでした。

[code]

    csv_data = '''
    id,timestamp
    idefs,2022-12-15T00:00:01.0000000Z
    idefs,2022-12-15T00:00:02.0000000Z
    idefs,2022-12-15T00:00:03.0000000Z
    idefs,2022-12-15T00:00:04.0000000Z
    aaefsd,2022-12-15T00:00:05.0000000Z
    idefs,2022-12-15T00:00:06.0000000Z
    aaefsd,2022-12-15T00:00:07.0000000Z
    aaefsd,2022-12-15T00:00:08.0000000Z
    qwerty,2022-12-15T00:00:09.0000000Z
    aaefsd,2022-12-15T00:00:10.0000000Z
    aaefsd,2022-12-15T00:00:11.0000000Z
    qwerty,2022-12-15T00:00:12.0000000Z
    qwerty,2022-12-15T00:00:13.0000000Z
    qwerty,2022-12-15T00:00:14.0000000Z
    qwerty,2022-12-15T00:00:15.0000000Z
    '''
    
    df = pd.read_csv(csv_data)
    
    df.sort_values(['id', 'timestamp']) 
    
[/code]

**結果**

[code]

            id                     timestamp
    4   aaefsd  2022-12-15T00:00:05.0000000Z
    6   aaefsd  2022-12-15T00:00:07.0000000Z
    7   aaefsd  2022-12-15T00:00:08.0000000Z
    9   aaefsd  2022-12-15T00:00:10.0000000Z
    10  aaefsd  2022-12-15T00:00:11.0000000Z
    0    idefs  2022-12-15T00:00:01.0000000Z
    1    idefs  2022-12-15T00:00:02.0000000Z
    2    idefs  2022-12-15T00:00:03.0000000Z
    3    idefs  2022-12-15T00:00:04.0000000Z
    5    idefs  2022-12-15T00:00:06.0000000Z
    8   qwerty  2022-12-15T00:00:09.0000000Z
    11  qwerty  2022-12-15T00:00:12.0000000Z
    12  qwerty  2022-12-15T00:00:13.0000000Z
    13  qwerty  2022-12-15T00:00:14.0000000Z
    14  qwerty  2022-12-15T00:00:15.0000000Z
    
[/code]

**追加質問**  
下記のようにidに空白がある場合に下記の加工後データにしたい場合、先ほどと同じようにグルーピング化して処理を行うことは可能でしょうか？  
**元データ(csv形式)**

[code]

    id,timestamp
    idefs,2022-12-15T00:00:01.0000000Z
    idefs,2022-12-15T00:00:02.0000000Z
    idefs,2022-12-15T00:00:03.0000000Z
    idefs,2022-12-15T00:00:04.0000000Z
    aaefsd,2022-12-15T00:00:05.0000000Z
    idefs,2022-12-15T00:00:06.0000000Z
    ,2022-12-15T00:00:07.0000000Z
    aaefsd,2022-12-15T00:00:08.0000000Z
    aaefsd,2022-12-15T00:00:09.0000000Z
    qwerty,2022-12-15T00:00:10.0000000Z
    aaefsd,2022-12-15T00:00:11.0000000Z
    aaefsd,2022-12-15T00:00:12.0000000Z
    qwerty,2022-12-15T00:00:13.0000000Z
    qwerty,2022-12-15T00:00:14.0000000Z
    qwerty,2022-12-15T00:00:15.0000000Z
    qwerty,2022-12-15T00:00:16.0000000Z
    
[/code]

**加工後データ(csv形式)**

[code]

    id,timestamp
    idefs,2022-12-15T00:00:01.0000000Z
    idefs,2022-12-15T00:00:02.0000000Z
    idefs,2022-12-15T00:00:03.0000000Z
    idefs,2022-12-15T00:00:04.0000000Z
    idefs,2022-12-15T00:00:06.0000000Z
    aaefsd,2022-12-15T00:00:05.0000000Z
    aaefsd,2022-12-15T00:00:08.0000000Z
    aaefsd,2022-12-15T00:00:09.0000000Z
    aaefsd,2022-12-15T00:00:11.0000000Z
    aaefsd,2022-12-15T00:00:12.0000000Z
    ,2022-12-15T00:00:07.0000000Z
    qwerty,2022-12-15T00:00:10.0000000Z
    qwerty,2022-12-15T00:00:13.0000000Z
    qwerty,2022-12-15T00:00:14.0000000Z
    qwerty,2022-12-15T00:00:15.0000000Z
    qwerty,2022-12-15T00:00:16.0000000Z
    
[/code]


CC BY-SA 4.0
2023-01-03T15:11:26.307
93170
2023-01-04T06:36:51.167
2023-01-04T04:39:01.187
47546
47546
question
python pandas
pandasで同一idはまとめて出力し、そのうえでtimestamp順に出力したい。


> こちら、カラムがid,timestamp以外に複数あり、そちらのすべてを復元したい場合、どのような記載ができますでしょうか？

>
> こちら複数の空白行がある場合、一か所に固まってしまいます。これらの空白行もidのまとまりを崩さないようにtimestampで昇順に並べることは可能でしょうか？

`id` が空欄のデータに何の意味があるのか不明ですが(ログデータを出力しているシステムの不備でしょう)、とりあえずは以下の様になります。

[code]

    dfx = df.assign(_subid = df.groupby('id', group_keys=False, sort=False, dropna=False)\
                               .apply(lambda x: x['id'].isna().cumsum()))\
            .groupby(['id', '_subid'], sort=False, dropna=False)\
            .apply(lambda x: x.sort_values('timestamp', ignore_index=True))\
            .reset_index(drop=True)[df.columns]
    
[/code]


CC BY-SA 4.0
2023-01-03T16:16:26.107
93171
2023-01-04T06:36:51.167
2023-01-04T06:36:51.167
47127
47127
93170
answer


「加工したいデータ」の id順 は 「元データ」の id の出現順である、との仮定で回答します。  
※ pandasのバージョンが1.1.0であること

[code]

    import pandas as pd
    import io
    
    data = """
    id,timestamp
    idefs,2022-12-15T00:00:01.0000000Z
    idefs,2022-12-15T00:00:02.0000000Z
    idefs,2022-12-15T00:00:03.0000000Z
    idefs,2022-12-15T00:00:04.0000000Z
    aaefsd,2022-12-15T00:00:05.0000000Z
    idefs,2022-12-15T00:00:06.0000000Z
    aaefsd,2022-12-15T00:00:07.0000000Z
    aaefsd,2022-12-15T00:00:08.0000000Z
    qwerty,2022-12-15T00:00:09.0000000Z
    aaefsd,2022-12-15T00:00:10.0000000Z
    aaefsd,2022-12-15T00:00:11.0000000Z
    qwerty,2022-12-15T00:00:12.0000000Z
    qwerty,2022-12-15T00:00:13.0000000Z
    qwerty,2022-12-15T00:00:14.0000000Z
    qwerty,2022-12-15T00:00:15.0000000Z
    """
    
    df = pd.read_csv(io.StringIO(data))
    df["timestamp"] = pd.to_datetime(df["timestamp"])
    print(df)
    #        id                 timestamp
    #0    idefs 2022-12-15 00:00:01+00:00
    #1    idefs 2022-12-15 00:00:02+00:00
    #2    idefs 2022-12-15 00:00:03+00:00
    #3    idefs 2022-12-15 00:00:04+00:00
    #4   aaefsd 2022-12-15 00:00:05+00:00
    #5    idefs 2022-12-15 00:00:06+00:00
    #6   aaefsd 2022-12-15 00:00:07+00:00
    #7   aaefsd 2022-12-15 00:00:08+00:00
    #8   qwerty 2022-12-15 00:00:09+00:00
    #9   aaefsd 2022-12-15 00:00:10+00:00
    #10  aaefsd 2022-12-15 00:00:11+00:00
    #11  qwerty 2022-12-15 00:00:12+00:00
    #12  qwerty 2022-12-15 00:00:13+00:00
    #13  qwerty 2022-12-15 00:00:14+00:00
    #14  qwerty 2022-12-15 00:00:15+00:00
    
    key_dict = {}
    for i, v in enumerate(df["id"].drop_duplicates()):
        key_dict[v] = i + 1
        
    def key(s):
        return s.map(key_dict) 
    
    df = df.sort_values(["id", "timestamp"], key = key)
    print(df)
    #        id                 timestamp
    #0    idefs 2022-12-15 00:00:01+00:00
    #1    idefs 2022-12-15 00:00:02+00:00
    #2    idefs 2022-12-15 00:00:03+00:00
    #3    idefs 2022-12-15 00:00:04+00:00
    #5    idefs 2022-12-15 00:00:06+00:00
    #4   aaefsd 2022-12-15 00:00:05+00:00
    #6   aaefsd 2022-12-15 00:00:07+00:00
    #7   aaefsd 2022-12-15 00:00:08+00:00
    #9   aaefsd 2022-12-15 00:00:10+00:00
    #10  aaefsd 2022-12-15 00:00:11+00:00
    #8   qwerty 2022-12-15 00:00:09+00:00
    #11  qwerty 2022-12-15 00:00:12+00:00
    #12  qwerty 2022-12-15 00:00:13+00:00
    #13  qwerty 2022-12-15 00:00:14+00:00
    #14  qwerty 2022-12-15 00:00:15+00:00
    
[/code]


CC BY-SA 4.0
2023-01-03T16:17:39.187
93172
2023-01-03T16:17:39.187
39819
93170
answer