Step 21:NumPy配列の演算

🧮 ステップ21: NumPy配列の演算

配列の計算をマスターして、データ分析の基礎を固めよう!

このステップでは、NumPy配列での演算(計算)を学びます。NumPyの真の力は「全ての要素に対して一度に計算できる」ことにあります。これをマスターすれば、データ分析の効率が大きく上がります!

📖 このステップで学ぶこと

・要素ごとの四則演算(+, -, *, /)

・ブロードキャスト(形の違う配列同士の計算)

・条件抽出(条件に合うデータだけを取り出す)

・np.where()での条件分岐

・便利な数学関数

学習時間の目安: 2.5〜3時間

🎯 1. 要素ごとの四則演算

NumPy配列の最大の特徴は、全ての要素に対して一度に計算できることです。

🔰 配列と数値の演算

配列に数値を足したり掛けたりすると、全ての要素に対してその計算が適用されます。

コード:配列全体に計算を適用

import numpy as np

# 商品の価格データ
prices = np.array([100, 200, 300, 400, 500])

print(f"元の価格: {prices}")
print()
print(f"2倍: {prices * 2}")
print(f"100円引き: {prices - 100}")
print(f"消費税10%込み: {prices * 1.1}")
print(f"半額: {prices / 2}")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

元の価格: [100 200 300 400 500]

2倍: [ 200  400  600  800 1000]
100円引き: [  0 100 200 300 400]
消費税10%込み: [110. 220. 330. 440. 550.]
半額: [ 50. 100. 150. 200. 250.]

💡 これがNumPyの威力!

普通のリストで同じことをしようとすると、forループが必要です:

result = [p * 2 for p in prices] # リストの場合

NumPyなら prices * 2 の1行で済みます!

しかも、NumPyの方が何十倍も速いのです。

📌 ベクトル化(Vectorization)

全ての要素に一度に計算を適用することをベクトル化といいます。

ループを書く必要がなく、高速読みやすいコードになります!

📘 配列同士の演算

同じサイズの配列同士を計算すると、対応する位置の要素同士が計算されます。

コード:配列同士の計算

import numpy as np

# 先週と今週の売上(万円)
last_week = np.array([120, 135, 150, 145, 160, 175, 180])
this_week = np.array([125, 140, 155, 150, 165, 180, 185])

print(f"先週の売上: {last_week}")
print(f"今週の売上: {this_week}")
print()

# 増減額(今週 - 先週)
increase = this_week - last_week
print(f"増減額: {increase}")

# 増加率(%)
increase_rate = (this_week - last_week) / last_week * 100
print(f"増加率: {increase_rate}")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

先週の売上: [120 135 150 145 160 175 180]
今週の売上: [125 140 155 150 165 180 185]

増減額: [5 5 5 5 5 5 5]
増加率: [4.16666667 3.7037037  3.33333333 3.44827586 3.125      2.85714286
 2.77777778]

💡 配列同士の計算の仕組み

先週: [120, 135, 150, …]

今週: [125, 140, 155, …]

増減: [125-120, 140-135, 155-150, …] = [5, 5, 5, …]

同じ位置の要素同士が計算されます。

📘 複数の演算を組み合わせる

複数の計算を組み合わせて、複雑な計算も簡単にできます。

コード:売上分析の計算

import numpy as np

# 商品の原価
cost = np.array([800, 1200, 1500, 2000])

# ステップ1: 利益率30%で販売価格を計算
selling_price = cost * 1.3
print(f"原価: {cost}円")
print(f"販売価格(利益率30%): {selling_price}円")

# ステップ2: 消費税10%を加える
final_price = selling_price * 1.1
print(f"税込価格: {final_price}円")

# ステップ3: 利益を計算
profit = final_price - cost
print(f"利益: {profit}円")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

原価: [ 800 1200 1500 2000]円
販売価格(利益率30%): [1040. 1560. 1950. 2600.]円
税込価格: [1144. 1716. 2145. 2860.]円
利益: [ 344.  516.  645.  860.]円

📡 2. ブロードキャスト

ブロードキャストは、NumPyの強力な機能の一つです。形の違う配列同士でも計算できるようになります。

🔰 ブロードキャストとは?

配列と1つの数値を計算したとき、NumPyは自動的にその数値を配列と同じ形に「拡張」して計算します。これがブロードキャストです。

コード:ブロードキャストの基本

import numpy as np

arr = np.array([1, 2, 3])

# 10を足す → 10が自動的に[10, 10, 10]に拡張される
result = arr + 10

print(f"配列: {arr}")
print(f"配列 + 10: {result}")
print()
print("内部的には: [1, 2, 3] + [10, 10, 10] = [11, 12, 13]")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

配列: [1 2 3]
配列 + 10: [11 12 13]

内部的には: [1, 2, 3] + [10, 10, 10] = [11, 12, 13]

💡 ブロードキャストのイメージ

「10」という1つの値が、配列と同じサイズに「コピー」されるイメージです。

ただし、実際にはコピーされず、効率的に計算されます。

📘 2次元配列でのブロードキャスト

コード:2次元配列に数値を足す

import numpy as np

# 3人×3科目の点数
scores = np.array([
    [80, 75, 90],
    [85, 92, 88],
    [78, 82, 85]
])

print("元の点数:")
print(scores)

# 全員に5点加点(ブロードキャスト)
adjusted = scores + 5
print("\n5点加点後:")
print(adjusted)

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

元の点数:
[[80 75 90]
 [85 92 88]
 [78 82 85]]

5点加点後:
[[85 80 95]
 [90 97 93]
 [83 87 90]]

📘 行ごと・列ごとに異なる計算

ブロードキャストを使うと、行ごとや列ごとに異なる値を適用することもできます。

コード:行ごとに異なる係数をかける

import numpy as np

# 3店舗×4日間の売上
sales = np.array([
    [100, 120, 130, 140],  # 店舗A
    [110, 125, 135, 145],  # 店舗B
    [105, 115, 125, 135]   # 店舗C
])

print("元の売上:")
print(sales)

# 各店舗に異なる係数をかける
# 店舗A: 1.1倍, 店舗B: 1.0倍, 店舗C: 1.2倍
coefficients = np.array([[1.1], [1.0], [1.2]])

adjusted_sales = sales * coefficients

print("\n調整後の売上:")
print(adjusted_sales)

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

元の売上:
[[100 120 130 140]
 [110 125 135 145]
 [105 115 125 135]]

調整後の売上:
[[110.  132.  143.  154. ]
 [110.  125.  135.  145. ]
 [126.  138.  150.  162. ]]

💡 コードの解説

coefficients = np.array([[1.1], [1.0], [1.2]])

・3行1列の配列を作成

・これが各行(店舗)に適用される係数

sales * coefficients

・ブロードキャストにより、各行に対応する係数がかけられる

・店舗Aの全データに1.1、店舗Bに1.0、店舗Cに1.2

📌 ブロードキャストの利点

利点 説明
メモリ効率 配列を実際にコピーしないので省メモリ
コードが簡潔 ループを書く必要がない
高速 NumPy内部で最適化された計算

🔍 3. 条件抽出

NumPyでは、条件に合うデータだけを取り出すことが簡単にできます。

🔰 条件に合う要素を抽出

配列に条件式を適用すると、条件に合う要素だけを取り出せます。

📝 書き方:条件抽出

配列[条件式]

例:scores[scores >= 80] → 80以上の要素だけを抽出

コード:条件に合う要素を抽出

import numpy as np

scores = np.array([95, 72, 88, 91, 65, 78, 85, 92, 70, 87])

print(f"全ての点数: {scores}")
print()

# 80点以上を抽出
high_scores = scores[scores >= 80]
print(f"80点以上: {high_scores}")

# 70点未満を抽出
low_scores = scores[scores < 70]
print(f"70点未満: {low_scores}")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

全ての点数: [95 72 88 91 65 78 85 92 70 87]

80点以上: [95 88 91 85 92 87]
70点未満: [65]

💡 条件抽出の仕組み

ステップ1:条件式が評価される

scores >= 80 → [True, False, True, True, False, ...]

ステップ2:Trueの位置の要素だけが抽出される

scores[True, False, ...] → [95, 88, 91, ...]

📘 複数条件での抽出

複数の条件を組み合わせることもできます。

📌 論理演算子

演算子 意味
& AND(かつ) (arr >= 80) & (arr < 90)
| OR(または) (arr < 60) | (arr >= 90)
~ NOT(否定) ~(arr >= 80)

重要:各条件は必ずカッコ()で囲んでください!

コード:複数条件での抽出

import numpy as np

scores = np.array([95, 72, 88, 91, 65, 78, 85, 92, 70, 87])

print(f"全ての点数: {scores}")
print()

# 80点以上90点未満(AND条件)
mid_scores = scores[(scores >= 80) & (scores < 90)]
print(f"80点以上90点未満: {mid_scores}")

# 70点未満または90点以上(OR条件)
extreme_scores = scores[(scores < 70) | (scores >= 90)]
print(f"70点未満または90点以上: {extreme_scores}")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

全ての点数: [95 72 88 91 65 78 85 92 70 87]

80点以上90点未満: [88 85 87]
70点未満または90点以上: [95 91 65 92]

⚠️ よくある間違い

❌ 間違い:scores >= 80 and scores < 90

 → Pythonの「and」は配列には使えません

✅ 正解:(scores >= 80) & (scores < 90)

 → NumPyの「&」を使い、条件はカッコで囲む

📘 np.where()で条件分岐

np.where()は、条件によって異なる値を返す関数です。Excelの「IF関数」に似ています。

📝 書き方:np.where()

np.where(条件, Trueの時の値, Falseの時の値)

条件がTrueなら2番目の値、Falseなら3番目の値が入ります。

コード:np.where()で合格/不合格を判定

import numpy as np

scores = np.array([95, 72, 88, 91, 65, 78, 85])

# 80点以上なら"合格"、未満なら"不合格"
result = np.where(scores >= 80, "合格", "不合格")

print(f"点数: {scores}")
print(f"結果: {result}")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

点数: [95 72 88 91 65 78 85]
結果: ['合格' '不合格' '合格' '合格' '不合格' '不合格' '合格']

コード:数値を条件で置き換える

import numpy as np

scores = np.array([95, 72, 88, 91, 65, 78, 85])

# 80点未満は0に置き換え
adjusted = np.where(scores >= 80, scores, 0)

print(f"元の点数: {scores}")
print(f"80点未満を0に: {adjusted}")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

元の点数: [95 72 88 91 65 78 85]
80点未満を0に: [95  0 88 91  0  0 85]

📘 複数条件での分類(成績のランク分け)

np.where()を入れ子にすると、複数の条件で分類できます。

コード:成績をランク分け

import numpy as np

scores = np.array([95, 72, 88, 91, 65, 78, 85, 50, 92, 70])

# 成績を分類
# 90点以上: A、80点以上: B、70点以上: C、60点以上: D、それ以外: F
grade = np.where(scores >= 90, "A",
         np.where(scores >= 80, "B",
         np.where(scores >= 70, "C",
         np.where(scores >= 60, "D", "F"))))

print(f"点数: {scores}")
print(f"成績: {grade}")

# 集計
print("\n成績別人数:")
for g in ["A", "B", "C", "D", "F"]:
    count = np.count_nonzero(grade == g)
    print(f"  {g}: {count}人")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

点数: [95 72 88 91 65 78 85 50 92 70]
成績: ['A' 'C' 'B' 'A' 'D' 'C' 'B' 'F' 'A' 'C']

成績別人数:
  A: 3人
  B: 2人
  C: 3人
  D: 1人
  F: 1人

🧮 4. 便利な数学関数

NumPyには、データ分析で便利な数学関数がたくさん用意されています。

📘 絶対値・平方根・累乗

コード:基本的な数学関数

import numpy as np

numbers = np.array([-5, -3, 0, 3, 5])

print(f"元の数値: {numbers}")
print(f"絶対値 np.abs(): {np.abs(numbers)}")
print(f"2乗 np.square(): {np.square(numbers)}")
print(f"3乗 np.power(x, 3): {np.power(numbers, 3)}")

# 平方根は正の数のみ
positive = np.array([1, 4, 9, 16, 25])
print(f"\n平方根 np.sqrt(): {np.sqrt(positive)}")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

元の数値: [-5 -3  0  3  5]
絶対値 np.abs(): [5 3 0 3 5]
2乗 np.square(): [25  9  0  9 25]
3乗 np.power(x, 3): [-125  -27    0   27  125]

平方根 np.sqrt(): [1. 2. 3. 4. 5.]

📘 四捨五入・切り上げ・切り捨て

コード:丸め関数

import numpy as np

prices = np.array([1234.5, 5678.9, 9012.3, 3456.7])

print(f"元の価格: {prices}")
print()
print(f"四捨五入 np.round(): {np.round(prices)}")
print(f"切り上げ np.ceil(): {np.ceil(prices)}")
print(f"切り捨て np.floor(): {np.floor(prices)}")

# 小数第1位で四捨五入
values = np.array([1.234, 5.678, 9.012])
print(f"\n小数第1位で四捨五入: {np.round(values, 1)}")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

元の価格: [1234.5 5678.9 9012.3 3456.7]

四捨五入 np.round(): [1234. 5679. 9012. 3457.]
切り上げ np.ceil(): [1235. 5679. 9013. 3457.]
切り捨て np.floor(): [1234. 5678. 9012. 3456.]

小数第1位で四捨五入: [1.2 5.7 9. ]

📘 対数・指数関数

データ分析では、対数変換指数関数もよく使います。

コード:対数と指数

import numpy as np

numbers = np.array([1, 10, 100, 1000])

print(f"元の数値: {numbers}")
print(f"自然対数 np.log(): {np.log(numbers)}")
print(f"常用対数 np.log10(): {np.log10(numbers)}")

# 指数関数
exponents = np.array([0, 1, 2, 3])
print(f"\ne^x np.exp(): {np.exp(exponents)}")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

元の数値: [   1   10  100 1000]
自然対数 np.log(): [0.         2.30258509 4.60517019 6.90775528]
常用対数 np.log10(): [0. 1. 2. 3.]

e^x np.exp(): [ 1.          2.71828183  7.3890561  20.08553692]

💡 対数の使いどころ

np.log10()(常用対数)

・桁数が大きく違うデータを扱いやすくする

・10→1、100→2、1000→3 と変換される

np.log()(自然対数)

・成長率の計算などで使用

・機械学習でもよく使われる

📌 よく使う数学関数一覧

関数 説明
np.abs() 絶対値 np.abs(-5) → 5
np.sqrt() 平方根 np.sqrt(16) → 4
np.square() 2乗 np.square(3) → 9
np.round() 四捨五入 np.round(3.6) → 4
np.ceil() 切り上げ np.ceil(3.1) → 4
np.floor() 切り捨て np.floor(3.9) → 3
np.log() 自然対数 np.log(e) → 1
np.log10() 常用対数 np.log10(100) → 2
np.exp() 指数関数(e^x) np.exp(1) → 2.718

📊 5. 実践:売上データの計算

📘 例1:月別売上分析

コード:年間売上を分析する

import numpy as np

# 月別売上(万円)
monthly_sales = np.array([120, 135, 150, 145, 160, 175, 180, 190, 185, 170, 160, 200])
months = ['1月', '2月', '3月', '4月', '5月', '6月', 
          '7月', '8月', '9月', '10月', '11月', '12月']

print("📊 年間売上分析")
print("=" * 50)

# 基本統計
print(f"年間合計: {np.sum(monthly_sales)}万円")
print(f"月平均: {np.mean(monthly_sales):.1f}万円")
max_idx = np.argmax(monthly_sales)
min_idx = np.argmin(monthly_sales)
print(f"最高売上: {months[max_idx]} {np.max(monthly_sales)}万円")
print(f"最低売上: {months[min_idx]} {np.min(monthly_sales)}万円")

# 目標達成率(目標150万円)
target = 150
achieved = np.count_nonzero(monthly_sales >= target)
print(f"\n目標{target}万円達成: {achieved}ヶ月 / 12ヶ月")

# 前月比成長
growth = monthly_sales[1:] - monthly_sales[:-1]
print(f"前月比平均: {np.mean(growth):+.1f}万円")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

📊 年間売上分析
==================================================
年間合計: 1970万円
月平均: 164.2万円
最高売上: 12月 200万円
最低売上: 1月 120万円

目標150万円達成: 9ヶ月 / 12ヶ月
前月比平均: +6.4万円

💡 コードの解説

monthly_sales[1:] - monthly_sales[:-1]

・monthly_sales[1:] → 2月〜12月のデータ

・monthly_sales[:-1] → 1月〜11月のデータ

・引き算 → 各月の前月比が計算される

📘 例2:商品別売上の分析

コード:商品の売上構成比を分析

import numpy as np

# 商品データ
products = ['商品A', '商品B', '商品C', '商品D', '商品E']
quantities = np.array([150, 200, 120, 180, 90])  # 販売数
unit_prices = np.array([1000, 1500, 2000, 1200, 3000])  # 単価

# 売上を計算(販売数 × 単価)
sales = quantities * unit_prices

print("📦 商品別売上分析")
print("=" * 60)

# 各商品の情報を表示
for product, qty, price, sale in zip(products, quantities, unit_prices, sales):
    print(f"{product}: {qty:>4}個 × {price:>5}円 = {sale:>8}円")

print("-" * 60)
print(f"合計: {np.sum(quantities):>4}個         {np.sum(sales):>8}円")

# 売上構成比
sales_ratio = sales / np.sum(sales) * 100
print("\n売上構成比:")
for product, ratio in zip(products, sales_ratio):
    print(f"  {product}: {ratio:.1f}%")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

📦 商品別売上分析
============================================================
商品A:  150個 ×  1000円 =   150000円
商品B:  200個 ×  1500円 =   300000円
商品C:  120個 ×  2000円 =   240000円
商品D:  180個 ×  1200円 =   216000円
商品E:   90個 ×  3000円 =   270000円
------------------------------------------------------------
合計:  740個              1176000円

売上構成比:
  商品A: 12.8%
  商品B: 25.5%
  商品C: 20.4%
  商品D: 18.4%
  商品E: 23.0%

📘 例3:複数店舗の売上比較

コード:店舗別・日別の売上分析

import numpy as np

# 3店舗×7日間の売上(千円)
sales = np.array([
    [50, 62, 58, 71, 65, 88, 92],  # 店舗A
    [45, 55, 60, 68, 70, 85, 90],  # 店舗B
    [52, 58, 55, 65, 68, 82, 88]   # 店舗C
])

stores = ['店舗A', '店舗B', '店舗C']
days = ['月', '火', '水', '木', '金', '土', '日']

print("🏪 店舗別売上分析(単位:千円)")
print("=" * 60)

# 店舗別サマリー
print("店舗別サマリー:")
for i, store in enumerate(stores):
    total = np.sum(sales[i])
    avg = np.mean(sales[i])
    max_day = days[np.argmax(sales[i])]
    print(f"  {store}: 合計{total}千円、平均{avg:.1f}千円、最高{max_day}曜日")

# 日別合計(全店舗)
daily_total = np.sum(sales, axis=0)
print("\n日別合計(全店舗):")
for day, total in zip(days, daily_total):
    print(f"  {day}曜日: {total}千円")

print(f"\n週間合計: {np.sum(sales)}千円")

※ 画面が小さい場合は、コードブロックを横にスクロールできます

実行結果

🏪 店舗別売上分析(単位:千円)
============================================================
店舗別サマリー:
  店舗A: 合計486千円、平均69.4千円、最高日曜日
  店舗B: 合計473千円、平均67.6千円、最高日曜日
  店舗C: 合計468千円、平均66.9千円、最高日曜日

日別合計(全店舗):
  月曜日: 147千円
  火曜日: 175千円
  水曜日: 173千円
  木曜日: 204千円
  金曜日: 203千円
  土曜日: 255千円
  日曜日: 270千円

週間合計: 1427千円

📝 練習問題

ここまで学んだことを、実際に手を動かして確認しましょう。

問題1:配列の四則演算(初級)

📋 問題

以下の配列の全ての要素に対して、以下の計算を行ってください:

1. 全ての要素に10を足す

2. 全ての要素を2倍にする

3. 全ての要素を1.5で割る

data = [20, 40, 60, 80, 100]

解答例を見る

コード

import numpy as np

data = np.array([20, 40, 60, 80, 100])

print(f"元のデータ: {data}")
print()
print(f"10を足す: {data + 10}")
print(f"2倍: {data * 2}")
print(f"1.5で割る: {data / 1.5}")

実行結果

元のデータ: [ 20  40  60  80 100]

10を足す: [ 30  50  70  90 110]
2倍: [ 40  80 120 160 200]
1.5で割る: [13.33333333 26.66666667 40.         53.33333333 66.66666667]

問題2:条件抽出(初級)

📋 問題

以下の点数データから、60点以上の点数だけを抽出してください。また、その個数も表示してください。

scores = [85, 55, 72, 48, 91, 63, 77, 58, 89, 51]

解答例を見る

コード

import numpy as np

scores = np.array([85, 55, 72, 48, 91, 63, 77, 58, 89, 51])

# 60点以上を抽出
passing = scores[scores >= 60]

print(f"全ての点数: {scores}")
print(f"60点以上: {passing}")
print(f"合格者数: {len(passing)}人")
print(f"合格率: {len(passing) / len(scores) * 100:.0f}%")

実行結果

全ての点数: [85 55 72 48 91 63 77 58 89 51]
60点以上: [85 72 91 63 77 89]
合格者数: 6人
合格率: 60%

問題3:配列同士の計算(中級)

📋 問題

先週と今週の売上データがあります。以下を計算してください:

1. 各日の売上増減額

2. 各日の増減率(%)

3. 最も増加した曜日

先週 = [100, 110, 105, 120, 115, 140, 150]
今週 = [105, 115, 110, 130, 125, 150, 160]

解答例を見る

コード

import numpy as np

last_week = np.array([100, 110, 105, 120, 115, 140, 150])
this_week = np.array([105, 115, 110, 130, 125, 150, 160])
days = ['月', '火', '水', '木', '金', '土', '日']

# 増減額
increase = this_week - last_week
print(f"増減額: {increase}")

# 増減率
rate = (this_week - last_week) / last_week * 100
print(f"増減率(%): {np.round(rate, 1)}")

# 最も増加した曜日
max_idx = np.argmax(increase)
print(f"\n最も増加: {days[max_idx]}曜日(+{increase[max_idx]}万円、+{rate[max_idx]:.1f}%)")

実行結果

増減額: [ 5  5  5 10 10 10 10]
増減率(%): [5.  4.5 4.8 8.3 8.7 7.1 6.7]

最も増加: 木曜日(+10万円、+8.3%)

問題4:np.where()を使った条件分岐(中級)

📋 問題

気温データがあります。20℃以上なら「暖かい」、20℃未満なら「寒い」という配列を作成してください。

temperatures = [18, 22, 19, 25, 17, 23, 21, 16, 24, 20]

解答例を見る

コード

import numpy as np

temperatures = np.array([18, 22, 19, 25, 17, 23, 21, 16, 24, 20])

# 条件分岐
weather = np.where(temperatures >= 20, "暖かい", "寒い")

print(f"気温: {temperatures}")
print(f"判定: {weather}")

# 集計
warm_days = np.count_nonzero(weather == "暖かい")
cold_days = np.count_nonzero(weather == "寒い")
print(f"\n暖かい日: {warm_days}日")
print(f"寒い日: {cold_days}日")

実行結果

気温: [18 22 19 25 17 23 21 16 24 20]
判定: ['寒い' '暖かい' '寒い' '暖かい' '寒い' '暖かい' '暖かい' '寒い' '暖かい' '暖かい']

暖かい日: 6日
寒い日: 4日

問題5:商品売上の分析(上級)

📋 問題

5商品の販売数と単価があります。以下を計算してください:

1. 各商品の売上

2. 売上合計

3. 売上が最も高い商品

4. 売上構成比(%)

販売数 = [120, 80, 150, 60, 100]
単価 = [500, 800, 400, 1200, 600]

解答例を見る

コード

import numpy as np

quantities = np.array([120, 80, 150, 60, 100])
prices = np.array([500, 800, 400, 1200, 600])
products = ['商品A', '商品B', '商品C', '商品D', '商品E']

# 売上計算
sales = quantities * prices

print("商品別売上:")
for product, sale in zip(products, sales):
    print(f"  {product}: {sale:,}円")

# 売上合計
total = np.sum(sales)
print(f"\n売上合計: {total:,}円")

# 最高売上商品
max_idx = np.argmax(sales)
print(f"最高売上: {products[max_idx]}({sales[max_idx]:,}円)")

# 構成比
ratio = sales / total * 100
print("\n売上構成比:")
for product, r in zip(products, ratio):
    print(f"  {product}: {r:.1f}%")

実行結果

商品別売上:
  商品A: 60,000円
  商品B: 64,000円
  商品C: 60,000円
  商品D: 72,000円
  商品E: 60,000円

売上合計: 316,000円
最高売上: 商品D(72,000円)

売上構成比:
  商品A: 19.0%
  商品B: 20.3%
  商品C: 19.0%
  商品D: 22.8%
  商品E: 19.0%

問題6:複雑な条件分岐と集計(上級)

📋 問題

テスト点数があります。以下の基準でランク分けし、各ランクの人数を集計してください:

・90点以上: S ・80点以上90点未満: A ・70点以上80点未満: B

・60点以上70点未満: C ・60点未満: D

scores = [95, 72, 88, 91, 65, 78, 85, 55, 92, 70, 83, 58, 87, 76, 90]

解答例を見る

コード

import numpy as np

scores = np.array([95, 72, 88, 91, 65, 78, 85, 55, 92, 70, 83, 58, 87, 76, 90])

# ランク分け
ranks = np.where(scores >= 90, "S",
         np.where(scores >= 80, "A",
         np.where(scores >= 70, "B",
         np.where(scores >= 60, "C", "D"))))

print(f"点数: {scores}")
print(f"ランク: {ranks}")

# 集計
print("\nランク別集計:")
for rank in ["S", "A", "B", "C", "D"]:
    count = np.count_nonzero(ranks == rank)
    percentage = count / len(scores) * 100
    print(f"  {rank}: {count}人({percentage:.1f}%)")

実行結果

点数: [95 72 88 91 65 78 85 55 92 70 83 58 87 76 90]
ランク: ['S' 'B' 'A' 'S' 'C' 'B' 'A' 'D' 'S' 'B' 'A' 'D' 'A' 'B' 'S']

ランク別集計:
  S: 4人(26.7%)
  A: 4人(26.7%)
  B: 4人(26.7%)
  C: 1人(6.7%)
  D: 2人(13.3%)

🎯 このステップのまとめ

✅ 学んだこと

✓ 配列全体に一度に計算を適用できる(ベクトル化

ブロードキャストで形の違う配列同士も計算できる

✓ 条件式(配列[条件])で簡単にデータを抽出できる

np.where()で条件分岐ができる

✓ 論理演算子(&, |, ~)で複雑な条件も表現できる

✓ 様々な数学関数(abs, sqrt, round等)が使える

💡 NumPy完了!次はPandasへ

これでNumPyの基礎は完了です!以下ができるようになったはずです:

□ 配列全体に計算を適用できる

□ 条件式でデータを抽出できる

□ np.where()を使った条件分岐ができる

□ 実際のデータ分析に応用できる

次のステップからはPandasを学びます。NumPyの上に構築されたPandasは、さらに強力なデータ分析ツールです!

❓ よくある質問

Q1: ベクトル化はなぜ速いのですか?

A: NumPyは内部でC言語を使っており、ループを使わずに一度に全ての計算を行います。Pythonのforループより圧倒的に高速で、大量のデータでは10倍〜100倍の速度差が出ることもあります。

Q2: ブロードキャストはどんな時に使いますか?

A: 全ての要素に同じ値を適用したい時に便利です。例えば、全商品に10%値上げ、全生徒に5点加点などです。

Q3: 条件抽出で&とandの違いは?

A: NumPy配列では&を使います。andはPythonの論理演算子で、配列には使えません。また、条件は必ずカッコ()で囲む必要があります。

Q4: np.where()はいつ使いますか?

A: 条件によって異なる値を設定したい時に使います。ExcelのIF関数のようなものです。

Q5: 元の配列を変更せずに計算するには?

A: copy()メソッドを使ってコピーを作成してから操作します。new_arr = arr.copy()。これをしないと、元の配列も変更されてしまうことがあります。

📝

学習メモ

Pythonデータ分析入門 - Step 21

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE