0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

データサイエンス100本ノック 59~60

Last updated at Posted at 2024-04-20

標準化、正規化

59 標準化

標準化とは平均が0、分散・標準偏差が1になるように変換することです。
Rでは標準化を行うためのライブラリが提供されてます。

 
用途
scale(x, center = TRUE, scale = TRUE)
引数1
center = TRUEで各データから平均が引かれる
引数2
scale = TRUEで各データが標準偏差で割られる

売上金を顧客IDごとに合計して、その金額を標準化する問題です

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

59
# Rのscaleを使用しているため不変分散の平方根による標準偏差で標準化される
df_receipt %>% 
        filter(!grepl("^Z",customer_id)) %>%
        group_by(customer_id) %>%
        summarise(sum_amount = sum(amount), .groups = 'drop') %>%
        mutate(std_amount = scale(sum_amount, center = TRUE, scale = TRUE)) %>%
        slice(1:10)

60 正規化

正規化とは各データから「最小値」を引き、「最大値ー最小値」で割ることで、
データが0~1の範囲に収まるようにすることです。

 
用途
scale(x, center = TRUE, scale = TRUE)
引数1
center = min(x)で各データから平均が引かれる
引数2
scale = max(x)-min(x)で各データが標準偏差で割られる

売上金を顧客IDごとに合計して、その金額を正規化する問題です

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

060
df_receipt %>% 
    filter(!grepl("^Z", customer_id)) %>%
    group_by(customer_id) %>%
    summarise(sum_amount = sum(amount), .groups = 'drop') %>%
    mutate(
        scale_amount = scale(sum_amount, 
                             center = min(sum_amount),
                             scale = max(sum_amount) - min(sum_amount))) %>%
    slice(1:10)

参考

scalecenterで指定した値を引き、scaleで指定した値を割ることもできる

scale関数の上記の問題以外での活用法です

scale
# ベクトルデータの作成
vector <- c(10, 20, 30, 40, 50)

# 平均100、標準偏差15でスケーリング
scaled_vector <- scale(vector, center = 100, scale = 15)

# 結果の表示
print(scaled_vector)

61 対数変換(常用対数)

データが小さい時はその範囲が拡大され、データが大きい時はその範囲が縮小されるため、対数化を行うことでデータを正規分布に近づけることができます。

特徴量エンジニアリングとして最初に検討するのが対数変換です
それによって、ロングテイルデータを正規分布に近づけることができます
数値データの取り扱いについて(外部ページ)

Usage
log(x, base = exp(1))
Arguments
x
数値(か複素数)
base
対数を計算する際の底
デフォルトはネイピア数e

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

061
df_receipt %>%
    filter(!grepl("^Z",customer_id)) %>%
    group_by(customer_id) %>%
    summarise(sum_amount = sum(amount), .groups = "drop") %>%
    mutate(log_amount = log(sum_amount + 0.5), base = 10) %>%
    slice(1:5)

62 対数変換(自然対数)

先ほどの常用対数を自然対数にしたバージョンです

Usage
log(x, base = exp(1))
Arguments
x
数値(か複素数)
base
対数を計算する際の底
デフォルトはネイピア数e

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

062
df_receipt %>% 
    filter(!grepl("^Z",customer_id)) %>%
    group_by(customer_id) %>%
    summarise(sum_amount = sum(amount), .groups = "drop") %>%
    mutate(log_amount = log(sum_amount + 0.5)) %>%
    slice(1:5)

63 四則演算

引き算、割り算をやります

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

063
df_product %>%
        mutate(unit_profit = unit_price - unit_cost) %>%
        select(product_cd,unit_price,unit_cost,unit_profit) %>%
        slice(1:5)

64 四則演算

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

064
df_product %>% 
        mutate(unit_profit_rate = (unit_price - unit_cost)/ unit_price *100) %>%
        summarise(average_profit_rate = mean(unit_profit_rate, na.rm = TRUE))

69 集計結果から割合を求める

この問題では、以下が要件となっている。
①レシート明細データと商品データを結合する
②全商品の売上金額合計とカテゴリ大区分コード07の売上金額合計を計算
③”07/全商品”を求める
④結果を10件表示する

R-069: レシート明細データ(df_receipt)と商品データ(df_product)を結合し、顧客毎に全商品の売上金額合計と、カテゴリ大区分コード(category_major_cd)が"07"(瓶詰缶詰)の売上金額合計を計算の上、両者の比率を求めよ。抽出対象はカテゴリ大区分コード"07"(瓶詰缶詰)の売上実績がある顧客のみとし、結果を10件表示せよ。

069 回答
df_receipt %>% 
        left_join(df_product,by = "product_cd") %>%
        group_by(customer_id) %>%
        summarise(sum_percustomer = sum(amount), .groups = "drop")%>%
        left_join(df_receipt, by = "customer_id") %>%
        left_join(df_product,by = "product_cd") %>%
        filter(category_major_cd == "07") %>%
        group_by(customer_id) %>%
        summarise(sum_07 = sum(amount),sum_percustomer = max(sum_percustomer),.groups = "drop") %>%
        mutate(sales_rate = sum_07/sum_percustomer) %>%
        arrange(desc(sum_percustomer)) %>%
        slice(1:5)
069 教科書解答
# df_tmp_1では顧客別の全売上金額合計を算出する
df_tmp_1 <- df_receipt %>%
        group_by(customer_id) %>%
        summarize(sum_all = sum(amount))

# df_tmp_2ではカテゴリ大区分コード07の売上金額合計を算出する
df_tmp_2 <- inner_join(df_receipt,
                       df_product[c("product_cd","category_major_cd")],
                       by = "product_cd") %>%
            # カテゴリ大区分コード別で集計したいためfilterで抽出する
            filter(category_major_cd == "07") %>%
            group_by(customer_id) %>%
            summarize(sum_07 = sum(amount),.groups = "drop")

# 最後にで売上合計金額の2つのデータを結合して加える
inner_join(df_tmp_1,df_tmp_2,by = "customer_id") %>%
            mutate(sum_rate = sum_07/sum_all*100) %>%
            arrange(desc(sum_07)) %>%
            slice(1:5)

070 顧客

初級者にとってはかなり苦戦させられた。
というのも、どのような関数と引数で日付型の変数に変換するのか?
経過日数をどのようにすれば計算できるのかが慣れていないからだ。
さっそく、取り組もう

この問題では以下が要件となっている。
①レシート明細データの売上日から顧客データの会員申込日の経過日数を計算

1-1 レシート明細データと顧客データを結合する
1-2 売上日と会員申込日を計算できるように揃える

②顧客ID,売上日,会員申込日,経過日数を表示

R-070: レシート明細データ(df_receipt)の売上日(sales_ymd)に対し、顧客データ(df_customer)の会員申込日(application_date)からの経過日数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)

070
df_merged <- inner_join(df_receipt,df_customer,by = "customer_id")

df_merged <- df_merged %>% 
            mutate(sales_ymd = as.Date(as.character(sales_ymd),format = "%Y%m%d"),
                    application_date = as.Date(application_date,format = "%Y%m%d")) %>%
            mutate(passed_date = as.numeric(difftime(application_date,sales_ymd,units = "days")))%>%
            select(customer_id,application_date,sales_ymd,passed_date) %>%
            slice(1:5)

分析の引き出しになったという所感だ。
気が向いたら随時更新する。

以上

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?