これはデータサイエンティストの卵がわけもわからないまま100本ノックを行っていく奮闘録である。
完走できるか謎。途中で消えてもQiitaにあげてないだけと思ってください。
ネタバレも含みますのでやろうとされている方は注意
記事を書く時点で27本目まで終わっていますが、知らなかった書き方も多く、また「自分はこう書いたけど答えはこうだった」というものも多くあったのでメモ代わりに置いておきます。
コレは見づらい!この書き方は危険!等ありましたら教えていただきたいです。心にダメージを負いながら糧とさせていただきます。
戦いはここから始まる
#19本目
P-19: レシート明細データフレーム(df_receipt)に対し、1件あたりの売上金額(amount)が高い順にランクを付与し、先頭10件を抽出せよ。項目は顧客ID(customer_id)、売上金額(amount)、付与したランクを表示させること。なお、売上金額(amount)が等しい場合は同一順位を付与するものとする。
今回の要件は
id | amo | rank |
---|---|---|
A00 | 100 | 1 |
B00 | 70 | 2 |
C00 | 80 | 2 |
D00 | 70 | 4 |
みたいな形の表を作る、ということらしい | ||
SQLでいうなら |
SELECT id,amo amo,
(SELECT count(amo) FROM df b WHERE a.amo < b.amo)+1 rank
FROM df a ORDER BY rank
といったところか(久々にSQL打った)
一応解説するとamo
とa.amo
が今見ている売上で、その見ている売上よりも高い売上b.amo
の数をカウントして(一番大きいと0になるから)+1する。と、いうrankを作りその列を追加するという内容。
注意:とても計算に時間がかかる書き方です。10本ノックのSQLで試しましたが、数分単位でかかりました。
Dataframeでも同じように
df_receipt[['customer_id', 'amount']]
とランク列
を作り、(横に)結合すると表ができる
ランク列
の作り方は
df_receipt['amount'].rank(method='min', ascending=False)
※[参考]
-
ascending=False
で降順(多いほうが優先)データ。 -
method='min'
は少ない数(最小値)が順位データとして返る。
横結合をするには
pd.concat([['列A'],['列B']], axis=1)
pd.concat
はaxisがデフォルトだと縦結合(表の下に表がくっつく)が、axis=1
をつけると横結合されるらしい
最後に列名を変え、rank昇順に並び替えると
df_tmp = pd.concat([df_receipt[['customer_id', 'amount']] ,df_receipt['amount'].rank(method='min', ascending=False)], axis=1)
df_tmp.columns = ['customer_id', 'amount', 'ranking']
df_tmp.sort_values('ranking', ascending=True).head(10)
こうなる
もちろん分からなくてカンニングである
#20本目
df=df_receipt
df=pd.concat([df[['customer_id','amount']] ,df['amount'].rank(method='first',ascending=False) ],axis=1)
df.columns=['customer_id','amount','ranking']
df.sort_values('ranking',ascending=True).head(10)
19本目と内容が一部被るので割愛
変わる部分は
なお、売上金額(amount)が等しい場合でも別順位を付与すること。
の部分。つまり、表示として
id | amo | rank |
---|---|---|
A00 | 100 | 1 |
B00 | 70 | 2 |
C00 | 80 | 3 |
D00 | 70 | 4 |
という形をとりたい。 |
method='min'
は少ない数(最小値)が順位データとして返る。
ここを変更すればよく、降順データにした後に'min'
を'first'
とすることで出現順にナンバリングされる。
#21,22本目
len(df_receipt)
len(df_receipt['customer_id'].unique())
解説いる?
22本目をSQLに直すと
SELECT COUNT(DISTINCT customer_id) FROM receipt
でいけます。どっちが楽?
#今回はここまで
実際ランクをつけるのをSQLとPythonで比較してPythonのほうが早いと感じたので、ようやくpandasを使うことに意義を見出し始めました。LIKEとかSQLのが楽やろ
問題を解いているだけだとあまり頭に入ってこないので、また問題を解いてから整理をするをしていきたいと思います。