1列目の値に従って列に値を配置 – 任意列で行をグルーピングして列方向に展開(ピボット)

to arrange the value in columns as per value in 1st column – StackOverflow

まず,Pandas(Python)で考える.これ,未だに効率的な方法,というのが分からない.少なくとも,自分の中でリーズナブルチョイスが固まっていない.

%%writefile file
281475473926267,46,47
281474985385546,310,311
281474984889537,248,249
281475473926267,16,17
281474985385546,20,28
281474984889537,112,68

効率は悪いが,簡便な方法としては,「pandas.DataFrame.groupby.apply(list).apply(pd.Series)」だろう.listをsetにすれば重複を取り除けるし,ちょっとした処理には便利.

df = pd.read_csv('file', header=None)
df.melt(id_vars=0).groupby(0)['value'].apply(list).apply(pd.Series)
        0   1   2   3
0               
281474984889537 248 112 249 68
281474985385546 310 20  311 28
281475473926267 46  16  47  17

非常に効率が悪く,小規模データなら通用するが,中規模以上になると秒オーダー超える.また,ループを回してcollections.defaultdictを用いる方法もあるが,これも効率が悪い,というか更に効率が悪いので有意味ではない.

import pandas as pd
from collections import defaultdict


df = pd.read_csv('file', header=None, index_col=0)
dd = defaultdict(list)
for k, *v in df.itertuples():
    dd[k].extend(v)

res = pd.DataFrame.from_dict(dd, orient='index')
res
        0   1   2   3
281475473926267 46  47  16  17
281474985385546 310 311 20  28
281474984889537 248 249 112 68

時間効率が良いのは以下の様な方法で,meltした後,列方向のキーをアサインして(ピボットはヌルキーがあるとエラーになるので,この部分が重要),ピボットする.これは結構効率が良くて,中規模データ位は素早く処理できる.

df = pd.read_csv('file', header=None)
res = df.melt(id_vars=0)
col = res.groupby(0).cumcount()
res.assign(col=col).pivot(index=0, columns='col', values='value')
    col 0   1   2   3
0               
281474984889537 248 112 249 68
281474985385546 310 20  311 28
281475473926267 46  16  47  17
import pandas as pd
import numpy as np


df = pd.read_csv('file', header=None)
res = df.melt(id_vars=0)
col = res.groupby(0).cumcount()
res.assign(col=col).pivot(index=0, columns='col', values='value').apply(np.sort, 1)
    col 0   1   2   3
0               
281474984889537 68  112 248 249
281474985385546 20  28  310 311
281475473926267 16  17  46  47

  

ソートをしようと思うと,gawkの方が良い.

%%bash
time {
gawk 'BEGIN{FS=OFS=",";PROCINFO["sorted_in"] = "@ind_num_asc"}
{for(i=2;i<=NF;i++)a[$1][$i]}
END{for(k in a){s="";for(v in a[k])s=(s ? s"," : "")v;print k,s}}' file
}
281474984889537,68,112,248,249
281474985385546,20,28,310,311
281475473926267,16,17,46,47

real    0m0.005s
user    0m0.003s
sys 0m0.002s
広告
カテゴリー: 未分類 パーマリンク

1列目の値に従って列に値を配置 – 任意列で行をグルーピングして列方向に展開(ピボット) への1件のフィードバック

  1. ピンバック: 最初の列が同じ行をマージ – 行方向データを任意列でグルーピングして列方向へ展開 | 粉末@それは風のように (日記)

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中