アラフォーから色々始めるリケジョの独り言

アラフォーになって色々始めてみました手探りでがんばります。

【Python】100本ノックやってます。p‐62~p-65

P-062: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を自然対数化(底e)して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。

61やってればほぼコピペ。

 

P-063: 商品データ(df_product)の単価(unit_price)と原価(unit_cost)から各商品の利益額を算出し、結果を10件表示せよ。

 

P-064: 商品データ(df_product)の単価(unit_price)と原価(unit_cost)から、各商品の利益率の全体平均を算出せよ。ただし、単価と原価には欠損が生じていることに注意せよ。

 

P-065: 商品データ(df_product)の各商品について、利益率が30%となる新たな単価を求めよ。ただし、1円未満は切り捨てること。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。

 

算数。lambda使っちゃったけど、普通に算数で良かったっぽい。

【Python】100本ノックやってます。p‐62~p-65

P-062: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を自然対数化(底e)して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。

61やってればほぼコピペ。

 

P-063: 商品データ(df_product)の単価(unit_price)と原価(unit_cost)から各商品の利益額を算出し、結果を10件表示せよ。

 

P-064: 商品データ(df_product)の単価(unit_price)と原価(unit_cost)から、各商品の利益率の全体平均を算出せよ。ただし、単価と原価には欠損が生じていることに注意せよ。

 

P-065: 商品データ(df_product)の各商品について、利益率が30%となる新たな単価を求めよ。ただし、1円未満は切り捨てること。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。

 

算数。lambda使っちゃったけど、普通に算数で良かったっぽい。

【Python】100本ノックやってます。p‐58~p-61

P-058: 顧客データ(df_customer)の性別コード(gender_cd)をダミー変数化し、顧客ID(customer_id)とともに10件表示せよ。

ダミー変数とは何ぞやから始まる。

self-methods.com

これがわかれば特に難しいことはなし。

 

P-059: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を平均0、標準偏差1に標準化して顧客ID、売上金額合計とともに10件表示せよ。標準化に使用する標準偏差は、分散の平方根、もしくは不偏分散の平方根のどちらでも良いものとする。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。

ritsu-programming.hatenablog.com

意味が分からなすぎた、、、

www.codexa.net

 

標準化=一般的に平均0、分散と標準偏差が1になるように値を変化させる
正規化=一般的に最大値を1、最小値0にする

 

pandasに見慣れてしまったので、他のはちょっと、、、ってなって、pandasで解決したけど、解答を見るとまた違う感じ。

手段なんてものは調べれば出てくるので、そもそも正規化・標準化の意味を知る方が優先かな・・・(;´∀`)

 

P-060: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を最小値0、最大値1に正規化して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。

59で見たサイトを見てそのままやってみた。

pandasがやっぱりわかりやすい。

 

P-061: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を常用対数化(底10)して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。

Numpy使えば難しくはないんだけど、解答で+0.5してるのなんで・・・?これもまた数学的な知識不足のせいだな。

infoma-study.com

 

ほぼもう答えだけど笑。その理由がここに書いてあった。

omathin.com

これで完了ではありますが、常用対数化には注意点が必要です。

それは常用対数化するデータの中に0が含まれている場合の対応です。 常用対数化する際には10(0)は計算できないのです。高校数学で学ぶ真数条件というものですね。これに対処するために、一般的には1を加える対応を行います。なぜ1なのかという理由は特に存在しないようです。

 

そもそも対数化の目的がわからないのと、対数が何を示しているのかがわからないから、1を足してもいい理由がわからない・・・

【Python】100本ノックやってます。p‐56~p-57

P-056: 顧客データ(df_customer)の年齢(age)をもとに10歳刻みで年代を算出し、顧客ID(customer_id)、生年月日(birth_day)とともに10件表示せよ。ただし、60歳以上は全て60歳代とすること。年代を表すカテゴリ名は任意とする。

P-043で年代やってたからすんなり。

 

P-057: 056の抽出結果と性別コード(gender_cd)により、新たに性別×年代の組み合わせを表すカテゴリデータを作成し、10件表示せよ。組み合わせを表すカテゴリの値は任意とする。

strとかの型が合わないとかで色々躓いた、、、

str.cutが使えなくて、、、結局「+」で。

 

今日はふたつだけ。

【Python】100本ノックやってます。p‐51~p-55

P-051: レシート明細データ(df_receipt)の売上エポック秒を日付型に変換し、「日」だけ取り出してレシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。なお、「日」は0埋め2桁で取り出すこと。

P-50やれば瞬殺。

 

P-052: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計の上、売上金額合計に対して2,000円以下を0、2,000円より大きい金額を1に二値化し、顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。

 

total["amount"].map(lambda x : 0 if x <= 2000 else 1)

この書き方慣れない、、、、

 

P-053: 顧客データ(df_customer)の郵便番号(postal_cd)に対し、東京(先頭3桁が100〜209のもの)を1、それ以外のものを0に二値化せよ。さらにレシート明細データ(df_receipt)と結合し、全期間において売上実績のある顧客数を、作成した二値ごとにカウントせよ。

解答例とまた全然違うの作った、、、不細工なコードだなーとは思うんだけど。

df_customer["flag"] = df_customer["postal_cd"].str[0:3].astype(int).\
    map(lambda x : 1 if x >= 100 and x <= 209 else 0)

receipt_sum = df_receipt[~df_receipt["customer_id"].str.startswith("Z")][["customer_id","amount"]].\
    groupby("customer_id").sum().reset_index()

total = pd.merge(receipt_sum[["customer_id","amount"]], df_customer[["customer_id","postal_cd","flag"]], \
                 how="left", on="customer_id")

total[["flag","customer_id"]].groupby("flag").count()

アウトプットは一緒なのでとりあえずおけ。

 

P-054: 顧客データ(df_customer)の住所(address)は、埼玉県、千葉県、東京都、神奈川県のいずれかとなっている。都道府県毎にコード値を作成し、顧客ID、住所とともに10件表示せよ。値は埼玉県を11、千葉県を12、東京都を13、神奈川県を14とすること。

 

# 都道府県の抽出する正規表現パターンをつくる
pattern = '東京都|(千葉|埼玉|神奈川)県'

df_customer["pref"] = df_customer["address"].apply(lambda x:re.match(pattern,x).group())
df_customer[["customer_id","address","pref"]].\
    replace({'pref': {"埼玉県": 11, "千葉県": 12, "東京都": 13, "神奈川県": 14}}).head(10)

不細工な書き方(いったん別列に切り出してるところ)だなぁと思う。

解答の方も住所の最初3文字を取り出すっていうので神奈川だけ微妙な扱いにしてるの気持ち悪いけど。

 

P-055: レシート明細(df_receipt)データの売上金額(amount)を顧客ID(customer_id)ごとに合計し、その合計金額の四分位点を求めよ。その上で、顧客ごとの売上金額合計に対して以下の基準でカテゴリ値を作成し、顧客ID、売上金額合計とともに10件表示せよ。カテゴリ値は順に1〜4とする。

最小値以上第1四分位未満 ・・・ 1を付与 第1四分位以上第2四分位未満 ・・・ 2を付与 第2四分位以上第3四分位未満 ・・・ 3を付与 第3四分位以上 ・・・ 4を付与

複数条件による分岐の時どうするんだろうと思って、地道な方法しか思い浮かばなかったけど、applyを使って関数呼び出す感じが模範回答だった。そっちの方がいい気がする。applyまだ全然なじんでない感じがするなぁ・・・

 

total = df_receipt[["customer_id","amount"]].groupby("customer_id").sum()
quantile1,quantile2,quantile3 = total["amount"].quantile([0.25, 0.5, 0.75])

total.loc[total["amount"] < quantile1 ,"flag"] = 1
total.loc[(quantile1 <= total["amount"]) & (total["amount"] < quantile2), "flag"] = 2
total.loc[(quantile2 <= total["amount"]) & (total["amount"] < quantile3), "flag"] = 3
total.loc[quantile3 <= total["amount"],"flag"] = 4

total.head(10)

アウトプットは同じだったので及第点。

 

 

【Python】100本ノックやってます。p‐45~p-50+Djangoインストール

P-045: 顧客データ(df_customer)の生年月日(birth_day)は日付型でデータを保有している。これをYYYYMMDD形式の文字列に変換し、顧客ID(customer_id)とともに10件表示せよ。

 

df_customer["birth_day_str"] = df_customer["birth_day"].dt.strftime("%Y%m%d")

zとやってみたところ、

AttributeError: Can only use .dt accessor with datetimelike values

と出る。「ん?」と思って

 

df_customer.dtypes

とやってみたら

customer_id             object
customer_name           object
gender_cd                int64
gender                  object
birth_day               object
age                      int64
postal_cd               object
address                 object
application_store_cd    object
application_date         int64
status_cd               object
dtype: object

って出る。「birth_day」日付型じゃないってことだよな?お手本のデータ読み込みなおしてみたけど変わらず。エクセルで開いてみると日付型になってるっぽい気がするけど。

解答例を見ると

pd.to_datetime(df_customer['birth_day']).dt.strftime('%Y%m%d')

って書いてある。

一度日付型にしてから文字列にするってこと?

納得いってない・・・明日Slackで聞いてみよう。

 

P-046: 顧客データ(df_customer)の申し込み日(application_date)はYYYYMMDD形式の文字列型でデータを保有している。これを日付型に変換し、顧客ID(customer_id)とともに10件表示せよ。

 

こちらもなんか意味わからん。「application_date」が調べてみるとint型なんですけど。

int型を日付型に単純にしようとしたらうまくいかなかったので以下のサイトを参考にしてみた。

obenkyolab.com

 

P-047: レシート明細データ(df_receipt)の売上日(sales_ymd)はYYYYMMDD形式の数値型でデータを保有している。これを日付型に変換し、レシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。

46でやったことと同じことしてる、、、

 

P-048: レシート明細データ(df_receipt)の売上エポック秒(sales_epoch)は数値型のUNIX秒でデータを保有している。これを日付型に変換し、レシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。

unit="s"入れただけー

deepage.net

 

P-049: レシート明細データ(df_receipt)の売上エポック秒(sales_epoch)を日付型に変換し、「年」だけ取り出してレシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。

 

smart-hint.com

 

P-050: レシート明細データ(df_receipt)の売上エポック秒(sales_epoch)を日付型に変換し、「月」だけ取り出してレシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。なお、「月」は0埋め2桁で取り出すこと。

0埋め2桁ってことは文字列ってことだよなーって考えると難しくないかな。

 

 

ついに半分ー!!!!

今日は2時間半ぐらいやってたかな。

これやってると交感神経優位になっちゃって全然寝れないんだよな、、、でもやる時間って寝る前しかないし。

市販の睡眠導入剤だとあんまり効果感じなかったから、処方してもらうのもありだよなぁ。

効率よく寝たい。

 

あと、とりあえずDjangoインストールだけやった。

www.sejuku.net

【Python】100本ノックやってます。p‐44

P-044: 043で作成した売上サマリデータ(df_sales_summary)は性別の売上を横持ちさせたものであった。このデータから性別を縦持ちさせ、年代、性別コード、売上金額の3項目に変換せよ。ただし、性別コードは男性を"00"、女性を"01"、不明を"99"とする。

横持ちと縦持ちの話。

ググると色々出てくるけど、私は↓が一番わかりやすかった。

www.salesanalytics.co.jp

 

性別の表示の書き換えはreplace。

note.nkmk.me

 

まただいぶ解答例と違う回答をした、、、

stack_df_sales_summary = df_sales_summary.melt(
    id_vars = "ages",
    value_vars = ["0","1","9"],
    var_name = "gender",
    value_name = "amount"
)
stack_df_sales_summary.replace({"gender":{"0":"00","1":"01","9":"99"}}).\
    sort_values(by=["ages","gender"]).reset_index(drop=True)

でもまぁ同じ出力は出てるのでいいか。

解答例と同じ出力のためにソートはやってるからソートはおまけ。

 

多分これだけで1時間半~2時間ぐらいうなってた気がする、、、

まだまだアホなのです、、、

 

明日からまた平日なので今日はこれだけ。

 

フレームワークについても学びたい。Djangoが最優先、次点がFlask?

freelance-start.com