NumPy、Pandas、機械学習
RevealJS スライドでのスクロール
長いスライドコンテンツの場合:
ESC - 概要モードF - フルスクリーンS - 発表者モードimport numpy as np
# 配列作成
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(f"1次元配列: {arr1}") # [1 2 3 4 5]
print(f"2次元配列:\n{arr2}") # [[1 2 3], [4 5 6]]
print(f"形状: {arr2.shape}") # (2, 3)
print(f"データ型: {arr1.dtype}") # int64
# 便利な配列作成
zeros = np.zeros((3, 4)) # ゼロ配列
ones = np.ones((2, 3)) # 1で埋めた配列
range_arr = np.arange(0, 10, 2) # [0 2 4 6 8]
linspace = np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1. ]
random_arr = np.random.rand(3, 3) # ランダム配列
# 配列演算(ベクトル化)
arr = np.array([1, 2, 3, 4, 5])
print(arr * 2) # [2 4 6 8 10]
print(arr ** 2) # [1 4 9 16 25]
print(np.sqrt(arr)) # [1. 1.41 1.73 2. 2.24]# サンプルデータ
data = np.random.randn(1000) # 標準正規分布から1000個
# 基本統計
print(f"平均: {np.mean(data):.3f}")
print(f"標準偏差: {np.std(data):.3f}")
print(f"最小値: {np.min(data):.3f}")
print(f"最大値: {np.max(data):.3f}")
print(f"中央値: {np.median(data):.3f}")
# 配列の形状変更
matrix = np.arange(12).reshape(3, 4)
print(f"元の形状: {matrix.shape}")
print(f"転置: {matrix.T.shape}")
# インデックシング・スライシング
print(f"最初の行: {matrix[0]}")
print(f"最後の列: {matrix[:, -1]}")
print(f"条件フィルタ: {matrix[matrix > 5]}")
# 配列の結合
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
combined = np.concatenate([arr1, arr2]) # [1 2 3 4 5 6]
stacked = np.stack([arr1, arr2]) # [[1 2 3], [4 5 6]]
# 線形代数
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(f"行列積: \n{np.dot(A, B)}")
print(f"逆行列: \n{np.linalg.inv(A)}")
print(f"固有値: {np.linalg.eigvals(A)}")import pandas as pd
# Series(1次元データ)
series = pd.Series([1, 3, 5, 7, 9], index=['a', 'b', 'c', 'd', 'e'])
print(series)
# DataFrame(2次元データ)
data = {
'名前': ['太郎', '花子', '次郎', '美香'],
'年齢': [25, 30, 35, 28],
'職業': ['エンジニア', 'デザイナー', 'マネージャー', 'データサイエンティスト'],
'給与': [5000000, 4500000, 7000000, 6000000]
}
df = pd.DataFrame(data)
print(df) 名前 年齢 職業 給与
0 太郎 25 エンジニア 5000000
1 花子 30 デザイナー 4500000
2 次郎 35 マネージャー 7000000
3 美香 28 データサイエンティスト 6000000
# データの概要
print(df.info()) # データ型と欠損値情報
print(df.describe()) # 基本統計量
print(df.head()) # 最初の5行
print(df.tail(3)) # 最後の3行
# データ選択
print(df['名前']) # 列選択
print(df[['名前', '給与']]) # 複数列選択
print(df.iloc[0]) # 行選択(位置)
print(df.loc[df['年齢'] > 30]) # 条件選択
# データフィルタリング
高給与者 = df[df['給与'] > 5000000]
若い従業員 = df[df['年齢'] < 30]
エンジニア = df[df['職業'].str.contains('エンジニア')]
# データソート
年齢順 = df.sort_values('年齢')
給与降順 = df.sort_values('給与', ascending=False)
# グループ化と集約
職業別統計 = df.groupby('職業').agg({
'年齢': 'mean',
'給与': ['mean', 'max', 'min']
})
# 新しい列の追加
df['年収(万円)'] = df['給与'] / 10000
df['年齢グループ'] = pd.cut(df['年齢'], bins=[0, 30, 40, 100],
labels=['若手', '中堅', 'ベテラン'])# CSVファイルの読み込み
# df = pd.read_csv('data.csv', encoding='utf-8')
# 様々なファイル形式をサポート
# df = pd.read_excel('data.xlsx')
# df = pd.read_json('data.json')
# df = pd.read_sql('SELECT * FROM table', connection)
# サンプルデータ作成
import pandas as pd
import numpy as np
# 売上データのサンプル
np.random.seed(42)
dates = pd.date_range('2023-01-01', '2023-12-31', freq='D')
products = ['商品A', '商品B', '商品C', '商品D']
sales_data = []
for date in dates:
for product in products:
sales = np.random.poisson(lam=50) + np.random.randint(0, 100)
price = np.random.uniform(1000, 5000)
sales_data.append({
'日付': date,
'商品': product,
'販売数': sales,
'単価': round(price),
'売上': sales * round(price)
})
sales_df = pd.DataFrame(sales_data)
# データ保存
sales_df.to_csv('sales_data.csv', index=False, encoding='utf-8')
print("サンプルデータを保存しました")
print(sales_df.head())import matplotlib.pyplot as plt
plt.style.use('default') # スタイル設定
plt.rcParams['font.family'] = 'DejaVu Sans' # 日本語対応
# 基本的なプロット
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
# 線グラフ
x = np.linspace(0, 10, 100)
y = np.sin(x)
axes[0, 0].plot(x, y, 'b-', linewidth=2)
axes[0, 0].set_title('Sine Wave')
axes[0, 0].grid(True)
# 散布図
x_scatter = np.random.randn(100)
y_scatter = 2 * x_scatter + np.random.randn(100)
axes[0, 1].scatter(x_scatter, y_scatter, alpha=0.6)
axes[0, 1].set_title('Scatter Plot')
# ヒストグラム
data_hist = np.random.normal(0, 1, 1000)
axes[1, 0].hist(data_hist, bins=30, alpha=0.7, color='green')
axes[1, 0].set_title('Histogram')
# 棒グラフ
categories = ['A', 'B', 'C', 'D']
values = [23, 17, 35, 29]
axes[1, 1].bar(categories, values, color='orange')
axes[1, 1].set_title('Bar Chart')
plt.tight_layout()
plt.show()
# より高度な可視化
plt.figure(figsize=(10, 6))
# 複数系列のプロット
months = ['1月', '2月', '3月', '4月', '5月', '6月']
product_a = [120, 135, 158, 142, 167, 183]
product_b = [98, 112, 126, 139, 145, 156]
plt.plot(months, product_a, 'o-', label='商品A', linewidth=2, markersize=8)
plt.plot(months, product_b, 's-', label='商品B', linewidth=2, markersize=8)
plt.xlabel('月')
plt.ylabel('売上(万円)')
plt.title('月別売上推移')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()# 売上データの分析例
def analyze_sales_data():
# データ読み込み(前回作成したデータ)
df = sales_df.copy()
# 日付列をdatetime型に変換
df['日付'] = pd.to_datetime(df['日付'])
df['月'] = df['日付'].dt.month
df['曜日'] = df['日付'].dt.day_name()
# 基本統計
print("=== 基本統計 ===")
print(f"総売上: {df['売上'].sum():,}円")
print(f"平均日次売上: {df.groupby('日付')['売上'].sum().mean():,.0f}円")
print(f"最高日次売上: {df.groupby('日付')['売上'].sum().max():,}円")
# 商品別分析
print("\n=== 商品別分析 ===")
product_analysis = df.groupby('商品').agg({
'売上': ['sum', 'mean'],
'販売数': 'sum',
'単価': 'mean'
}).round(0)
print(product_analysis)
# 月別分析
monthly_sales = df.groupby('月')['売上'].sum()
# 曜日別分析
weekday_sales = df.groupby('曜日')['売上'].sum()
# 相関分析
correlation = df[['販売数', '単価', '売上']].corr()
print("\n=== 相関分析 ===")
print(correlation)
# 可視化
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 商品別売上
product_total = df.groupby('商品')['売上'].sum()
axes[0, 0].pie(product_total.values, labels=product_total.index, autopct='%1.1f%%')
axes[0, 0].set_title('商品別売上割合')
# 月別売上推移
axes[0, 1].plot(monthly_sales.index, monthly_sales.values, 'o-', linewidth=2)
axes[0, 1].set_title('月別売上推移')
axes[0, 1].set_xlabel('月')
axes[0, 1].set_ylabel('売上(円)')
axes[0, 1].grid(True)
# 販売数vs単価の散布図
axes[1, 0].scatter(df['販売数'], df['単価'], alpha=0.6)
axes[1, 0].set_title('販売数 vs 単価')
axes[1, 0].set_xlabel('販売数')
axes[1, 0].set_ylabel('単価(円)')
# 曜日別売上
weekday_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
weekday_sales_ordered = weekday_sales.reindex(weekday_order)
axes[1, 1].bar(range(7), weekday_sales_ordered.values)
axes[1, 1].set_title('曜日別売上')
axes[1, 1].set_xlabel('曜日')
axes[1, 1].set_ylabel('売上(円)')
axes[1, 1].set_xticks(range(7))
axes[1, 1].set_xticklabels(['月', '火', '水', '木', '金', '土', '日'])
plt.tight_layout()
plt.show()
return df
# 分析実行
analyzed_df = analyze_sales_data()from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
# サンプルデータ生成(住宅価格予測)
np.random.seed(42)
n_samples = 1000
# 特徴量: 面積、築年数、駅からの距離、部屋数
area = np.random.uniform(30, 150, n_samples)
age = np.random.uniform(0, 30, n_samples)
station_distance = np.random.uniform(1, 20, n_samples)
rooms = np.random.randint(1, 6, n_samples)
# 価格(目的変数): 面積と部屋数は正の影響、築年数と駅距離は負の影響
price = (area * 30 + rooms * 500 - age * 20 - station_distance * 50 +
np.random.normal(0, 300, n_samples))
price = np.maximum(price, 1000) # 最低価格を設定
# DataFrameに整理
housing_data = pd.DataFrame({
'面積': area,
'築年数': age,
'駅距離': station_distance,
'部屋数': rooms,
'価格': price
})
print("住宅データサンプル:")
print(housing_data.head())
print(f"\nデータ形状: {housing_data.shape}")
print("\n基本統計:")
print(housing_data.describe())# 特徴量と目的変数の分離
X = housing_data[['面積', '築年数', '駅距離', '部屋数']]
y = housing_data['価格']
# 訓練・テストデータの分割
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"訓練データ: {X_train.shape[0]}件")
print(f"テストデータ: {X_test.shape[0]}件")
# モデル1: 線形回帰
lr_model = LinearRegression()
lr_model.fit(X_train, y_train)
# モデル2: ランダムフォレスト
rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
# 予測
lr_pred = lr_model.predict(X_test)
rf_pred = rf_model.predict(X_test)
# 評価
def evaluate_model(y_true, y_pred, model_name):
mse = mean_squared_error(y_true, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_true, y_pred)
print(f"\n=== {model_name} ===")
print(f"RMSE: {rmse:.2f}")
print(f"R²スコア: {r2:.4f}")
return rmse, r2
lr_rmse, lr_r2 = evaluate_model(y_test, lr_pred, "線形回帰")
rf_rmse, rf_r2 = evaluate_model(y_test, rf_pred, "ランダムフォレスト")
# 特徴量重要度(ランダムフォレスト)
feature_importance = pd.DataFrame({
'特徴量': X.columns,
'重要度': rf_model.feature_importances_
}).sort_values('重要度', ascending=False)
print("\n特徴量重要度:")
print(feature_importance)
# 結果の可視化
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
# 実際 vs 予測(線形回帰)
axes[0].scatter(y_test, lr_pred, alpha=0.6)
axes[0].plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
axes[0].set_xlabel('実際の価格')
axes[0].set_ylabel('予測価格')
axes[0].set_title(f'線形回帰 (R² = {lr_r2:.3f})')
# 実際 vs 予測(ランダムフォレスト)
axes[1].scatter(y_test, rf_pred, alpha=0.6)
axes[1].plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
axes[1].set_xlabel('実際の価格')
axes[1].set_ylabel('予測価格')
axes[1].set_title(f'ランダムフォレスト (R² = {rf_r2:.3f})')
# 特徴量重要度
axes[2].barh(feature_importance['特徴量'], feature_importance['重要度'])
axes[2].set_xlabel('重要度')
axes[2].set_title('特徴量重要度')
plt.tight_layout()
plt.show()
# 新しいデータでの予測例
new_house = pd.DataFrame({
'面積': [80],
'築年数': [5],
'駅距離': [8],
'部屋数': [3]
})
lr_prediction = lr_model.predict(new_house)[0]
rf_prediction = rf_model.predict(new_house)[0]
print(f"\n新しい住宅の予測価格:")
print(f"面積: {new_house['面積'].iloc[0]}㎡, 築年数: {new_house['築年数'].iloc[0]}年, 駅距離: {new_house['駅距離'].iloc[0]}分, 部屋数: {new_house['部屋数'].iloc[0]}室")
print(f"線形回帰予測: {lr_prediction:,.0f}万円")
print(f"ランダムフォレスト予測: {rf_prediction:,.0f}万円")from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# 顧客データの生成
np.random.seed(42)
n_customers = 500
# 顧客の特徴量
age = np.random.normal(40, 12, n_customers)
income = np.random.normal(500, 150, n_customers) # 年収(万円)
spending = np.random.normal(300, 100, n_customers) # 年間支出(万円)
frequency = np.random.poisson(12, n_customers) # 年間購入回数
# 異常値の調整
age = np.clip(age, 18, 80)
income = np.clip(income, 200, 1000)
spending = np.clip(spending, 50, 800)
customer_data = pd.DataFrame({
'年齢': age,
'年収': income,
'年間支出': spending,
'購入回数': frequency
})
print("顧客データサンプル:")
print(customer_data.head())
print("\n基本統計:")
print(customer_data.describe())
# データの標準化
scaler = StandardScaler()
scaled_data = scaler.fit_transform(customer_data)
# K-means クラスタリング
kmeans = KMeans(n_clusters=4, random_state=42)
clusters = kmeans.fit_predict(scaled_data)
# クラスタ結果をデータに追加
customer_data['クラスタ'] = clusters
# クラスタ別分析
cluster_analysis = customer_data.groupby('クラスタ').agg({
'年齢': 'mean',
'年収': 'mean',
'年間支出': 'mean',
'購入回数': 'mean'
}).round(1)
print("\nクラスタ別分析:")
print(cluster_analysis)
# クラスタのラベル付け
cluster_labels = {
0: "若年層・高頻度",
1: "高所得者",
2: "シニア層",
3: "価格重視層"
}
customer_data['クラスタ名'] = customer_data['クラスタ'].map(cluster_labels)
# 可視化
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
# 年収 vs 年間支出
scatter = axes[0, 0].scatter(customer_data['年収'], customer_data['年間支出'],
c=customer_data['クラスタ'], cmap='viridis', alpha=0.7)
axes[0, 0].set_xlabel('年収(万円)')
axes[0, 0].set_ylabel('年間支出(万円)')
axes[0, 0].set_title('年収 vs 年間支出')
plt.colorbar(scatter, ax=axes[0, 0])
# 年齢 vs 購入回数
scatter2 = axes[0, 1].scatter(customer_data['年齢'], customer_data['購入回数'],
c=customer_data['クラスタ'], cmap='viridis', alpha=0.7)
axes[0, 1].set_xlabel('年齢')
axes[0, 1].set_ylabel('購入回数')
axes[0, 1].set_title('年齢 vs 購入回数')
# クラスタ別分布
cluster_counts = customer_data['クラスタ名'].value_counts()
axes[1, 0].pie(cluster_counts.values, labels=cluster_counts.index, autopct='%1.1f%%')
axes[1, 0].set_title('クラスタ別顧客分布')
# クラスタ別平均値比較
cluster_means = customer_data.groupby('クラスタ名')[['年収', '年間支出']].mean()
cluster_means.plot(kind='bar', ax=axes[1, 1])
axes[1, 1].set_title('クラスタ別平均年収・支出')
axes[1, 1].set_ylabel('金額(万円)')
axes[1, 1].tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.show()
# マーケティング戦略の提案
print("\n=== マーケティング戦略提案 ===")
for cluster_id, label in cluster_labels.items():
cluster_data = customer_data[customer_data['クラスタ'] == cluster_id]
size = len(cluster_data)
avg_income = cluster_data['年収'].mean()
avg_spending = cluster_data['年間支出'].mean()
avg_frequency = cluster_data['購入回数'].mean()
print(f"\n{label} ({size}人, {size/len(customer_data)*100:.1f}%)")
print(f" 平均年収: {avg_income:.0f}万円")
print(f" 平均支出: {avg_spending:.0f}万円")
print(f" 平均購入回数: {avg_frequency:.1f}回")
# 戦略提案
if cluster_id == 0:
print(" 戦略: デジタルマーケティング、頻繁な限定セール")
elif cluster_id == 1:
print(" 戦略: プレミアム商品、VIPサービス")
elif cluster_id == 2:
print(" 戦略: 健康・ライフスタイル商品、丁寧なサポート")
else:
print(" 戦略: 価格競争力、お得なバンドル商品")データサイエンスの世界へようこそ! 🔬📊
リソース: - NumPy ドキュメント - Pandas ドキュメント - Scikit-learn ドキュメント - Kaggle - データサイエンスコンペティション
Python チュートリアル