ソースネクスト | さよなら手書き 11 (最新版) | 書類記入・作成 ソフト | Windows対応
¥4,400 (2025-06-30 08:12 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)英語の発音をもう一度ひとつひとつわかりやすく。
¥1,760 (2025-06-30 08:12 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)KTC 27インチ QD-MiniLED 4K UHD 量子ドットゲーミングモニター|デュアルモード技術 320Hz/160Hz|HDR1400|Type-C 65W|HDMI2.1/DP1.4|Adaptive Sync|フリッカーフリー対応(DC調光)| KVM対応|145% sRGB|フル装備のエルゴノミクス機能 | PS5で120 Hz(VRR)対応 | 3年保証 M27P6
¥89,980 (2025-06-30 08:12 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)目次
Pandas入門:データ分析の基本操作完全ガイド
データ分析を始めるなら、Pandasは必須のライブラリです。この記事では、Pandasの基本的な使い方から実践的なデータ分析手法まで、初心者でもわかりやすく解説します。
Pandasとは?
Pandasの特徴
Pandas は、Pythonでデータ分析を行うための最も重要なライブラリの一つです。ExcelやSQLのような操作をPythonで簡単に実行できます。
主な機能
- データ構造: Series(1次元)、DataFrame(2次元)
- ファイルIO: CSV、Excel、JSON、SQL、Parquet対応
- データ操作: フィルタリング、ソート、グループ化、結合
- データクリーニング: 欠損値処理、重複削除、型変換
- 統計分析: 基本統計、集計、ピボットテーブル
- 時系列分析: 日付処理、リサンプリング、ローリング計算
環境構築とインストール
必要なライブラリのインストール
# 基本インストール
pip install pandas
# データ分析セット(推奨)
pip install pandas numpy matplotlib seaborn jupyter
# Excel対応
pip install openpyxl xlsxwriter
# 高速化
pip install fastparquet pyarrow
基本的なインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
# 表示設定
pd.set_option('display.max_columns', None) # 全列表示
pd.set_option('display.max_rows', 100) # 最大100行表示
pd.set_option('display.width', None) # 幅制限なし
pd.set_option('display.float_format', '{:.2f}'.format) # 小数点2桁
print("Pandas バージョン:", pd.__version__)
データ構造の基本:SeriesとDataFrame
Series:1次元データ
# Series の作成
import pandas as pd
import numpy as np
# リストから作成
prices = pd.Series([100, 150, 120, 180, 90])
print("価格データ:")
print(prices)
print()
# 辞書から作成
stock_prices = pd.Series({
'Apple': 150.0,
'Google': 2800.0,
'Microsoft': 300.0,
'Tesla': 800.0,
'Amazon': 3200.0
})
print("株価データ:")
print(stock_prices)
print()
# インデックス付きで作成
dates = pd.date_range('2024-01-01', periods=5, freq='D')
daily_sales = pd.Series([1000, 1200, 950, 1100, 1300], index=dates)
print("日別売上:")
print(daily_sales)
print()
# Series の基本操作
print("基本統計:")
print(f"平均: {stock_prices.mean():.2f}")
print(f"最大値: {stock_prices.max():.2f}")
print(f"最小値: {stock_prices.min():.2f}")
print(f"標準偏差: {stock_prices.std():.2f}")
DataFrame:2次元データ
# DataFrame の作成方法
# 1. 辞書から作成
sales_data = {
'商品名': ['商品A', '商品B', '商品C', '商品D', '商品E'],
'価格': [1000, 1500, 800, 2000, 1200],
'売上数': [100, 80, 150, 60, 120],
'カテゴリ': ['電子機器', '衣料品', '食品', '電子機器', '衣料品']
}
df_sales = pd.DataFrame(sales_data)
print("売上データ:")
print(df_sales)
print()
# 2. NumPy配列から作成
np.random.seed(42)
data = np.random.randn(5, 4)
columns = ['A', 'B', 'C', 'D']
index = ['行1', '行2', '行3', '行4', '行5']
df_random = pd.DataFrame(data, columns=columns, index=index)
print("ランダムデータ:")
print(df_random)
print()
# DataFrame の基本情報
print("DataFrame の基本情報:")
print(f"形状: {df_sales.shape}")
print(f"列名: {list(df_sales.columns)}")
print(f"インデックス: {list(df_sales.index)}")
print(f"データ型:n{df_sales.dtypes}")
ファイルの読み込みと保存
CSV ファイルの操作
# サンプルデータの作成と保存
sample_data = {
'date': pd.date_range('2024-01-01', periods=100, freq='D'),
'product': np.random.choice(['商品A', '商品B', '商品C'], 100),
'sales': np.random.randint(50, 200, 100),
'price': np.random.uniform(1000, 5000, 100),
'region': np.random.choice(['東京', '大阪', '名古屋'], 100)
}
df_sample = pd.DataFrame(sample_data)
# CSV に保存
df_sample.to_csv('sample_sales.csv', index=False, encoding='utf-8-sig')
print("サンプルデータを sample_sales.csv に保存しました")
# CSV から読み込み
df_loaded = pd.read_csv('sample_sales.csv', encoding='utf-8-sig')
print("CSV から読み込んだデータ:")
print(df_loaded.head())
print()
# 読み込み時のオプション
df_advanced = pd.read_csv(
'sample_sales.csv',
encoding='utf-8-sig',
parse_dates=['date'], # 日付列を自動変換
index_col='date', # 日付列をインデックスに
dtype={'sales': 'int32'}, # データ型を指定
nrows=10 # 最初の10行のみ読み込み
)
print("高度な読み込み:")
print(df_advanced.head())
Excel ファイルの操作
# Excel ファイルへの保存と読み込み
# 複数シートでの保存
with pd.ExcelWriter('sales_analysis.xlsx', engine='openpyxl') as writer:
# 元データ
df_sample.to_excel(writer, sheet_name='生データ', index=False)
# 商品別集計
product_summary = df_sample.groupby('product').agg({
'sales': ['sum', 'mean', 'count'],
'price': 'mean'
}).round(2)
product_summary.to_excel(writer, sheet_name='商品別集計')
# 地域別集計
region_summary = df_sample.groupby('region').agg({
'sales': 'sum',
'price': 'mean'
}).round(2)
region_summary.to_excel(writer, sheet_name='地域別集計')
print("Excel ファイル 'sales_analysis.xlsx' を作成しました")
# Excel から読み込み
try:
df_from_excel = pd.read_excel('sales_analysis.xlsx', sheet_name='生データ')
print("Excel から読み込み成功")
print(df_from_excel.head())
except FileNotFoundError:
print("Excel ファイルが見つかりません")
データの探索と概要把握
基本的なデータ探索
# データの基本情報を確認
print("データの形状:", df_sample.shape)
print("列の情報:")
print(df_sample.info())
print()
print("基本統計量:")
print(df_sample.describe())
print()
print("最初の5行:")
print(df_sample.head())
print()
print("最後の5行:")
print(df_sample.tail())
print()
print("ランダムサンプル:")
print(df_sample.sample(5))
print()
# 欠損値の確認
print("欠損値の確認:")
print(df_sample.isnull().sum())
print()
# ユニーク値の確認
print("各列のユニーク値数:")
for col in df_sample.columns:
print(f"{col}: {df_sample[col].nunique()}")
データ選択とフィルタリング
列の選択
# 列の選択方法
# 単一列の選択(Series として返される)
product_series = df_sample['product']
print("商品列(Series):")
print(product_series.head())
print(f"型: {type(product_series)}")
print()
# 複数列の選択
selected_cols = df_sample[['product', 'sales', 'price']]
print("複数列選択:")
print(selected_cols.head())
print()
# 数値列のみ選択
numeric_cols = df_sample.select_dtypes(include=[np.number])
print("数値列のみ:")
print(numeric_cols.head())
行の選択とフィルタリング
# 行の選択方法
# インデックスによる選択
print("最初の3行:")
print(df_sample.iloc[:3])
print()
# 条件によるフィルタリング
# 売上が100以上の行
high_sales = df_sample[df_sample['sales'] >= 100]
print(f"売上100以上: {len(high_sales)} 行")
print(high_sales.head())
print()
# 複数条件
tokyo_high_sales = df_sample[
(df_sample['region'] == '東京') &
(df_sample['sales'] >= 100)
]
print(f"東京かつ売上100以上: {len(tokyo_high_sales)} 行")
print(tokyo_high_sales.head())
print()
# query() メソッドの使用
query_result = df_sample.query('sales > 100 and region == "東京"')
print("query() の結果:")
print(query_result.head())
print()
# 上位/下位N件の取得
top_sales = df_sample.nlargest(5, 'sales')
print("売上トップ5:")
print(top_sales)
データクリーニング
欠損値の処理
# 欠損値を含むサンプルデータの作成
df_missing = df_sample.copy()
# 意図的に欠損値を作成
np.random.seed(42)
missing_indices = np.random.choice(df_missing.index, size=20, replace=False)
df_missing.loc[missing_indices, 'sales'] = np.nan
print("欠損値の確認:")
print(df_missing.isnull().sum())
print()
# 欠損値の処理方法
# 1. 欠損値のある行を削除
df_dropped = df_missing.dropna()
print(f"欠損値削除後: {len(df_dropped)} 行")
# 2. 欠損値を平均値で埋める
df_filled_mean = df_missing.copy()
df_filled_mean['sales'] = df_filled_mean['sales'].fillna(df_filled_mean['sales'].mean())
print("平均値で補完後の欠損値:")
print(df_filled_mean.isnull().sum())
# 3. 前の値で埋める(時系列データ)
df_ffill = df_missing.sort_values('date').fillna(method='ffill')
print("前方埋めの欠損値:")
print(df_ffill.isnull().sum())
# 4. 線形補間
df_interpolated = df_missing.copy()
df_interpolated['sales'] = df_interpolated['sales'].interpolate()
print("線形補間後の欠損値:")
print(df_interpolated.isnull().sum())
重複データの処理
# 重複データを含むサンプルの作成
df_with_duplicates = pd.concat([df_sample, df_sample.sample(10)], ignore_index=True)
print(f"重複を含むデータ: {len(df_with_duplicates)} 行")
print(f"重複行数: {df_with_duplicates.duplicated().sum()}")
# 重複の削除
df_no_duplicates = df_with_duplicates.drop_duplicates()
print(f"重複削除後: {len(df_no_duplicates)} 行")
# 特定列での重複削除
df_unique_products = df_with_duplicates.drop_duplicates(subset=['product', 'date'])
print(f"商品・日付の組み合わせで重複削除: {len(df_unique_products)} 行")
データの集計と統計
基本的な統計量
# 基本統計量の計算
print("数値データの基本統計:")
print(df_sample[['sales', 'price']].describe())
print()
# 個別統計量
print("個別統計量:")
print(f"売上の平均: {df_sample['sales'].mean():.2f}")
print(f"売上の中央値: {df_sample['sales'].median():.2f}")
print(f"売上の標準偏差: {df_sample['sales'].std():.2f}")
print(f"売上の分散: {df_sample['sales'].var():.2f}")
print()
# 相関係数
correlation = df_sample[['sales', 'price']].corr()
print("相関係数:")
print(correlation)
groupby による集計
# groupby による集計分析
# 1. 商品別集計
product_stats = df_sample.groupby('product').agg({
'sales': ['count', 'sum', 'mean', 'std'],
'price': ['mean', 'min', 'max']
}).round(2)
print("商品別統計:")
print(product_stats)
print()
# 2. 地域別集計
region_stats = df_sample.groupby('region').agg({
'sales': ['sum', 'mean'],
'price': 'mean'
}).round(2)
print("地域別統計:")
print(region_stats)
print()
# 3. 複数列でのグループ化
multi_group = df_sample.groupby(['region', 'product']).agg({
'sales': 'sum',
'price': 'mean'
}).round(2)
print("地域×商品別統計:")
print(multi_group)
ピボットテーブル
# ピボットテーブルの作成
# 基本的なピボットテーブル
pivot_basic = df_sample.pivot_table(
values='sales',
index='region',
columns='product',
aggfunc='sum',
fill_value=0
)
print("基本ピボットテーブル(地域×商品の売上合計):")
print(pivot_basic)
print()
# 複数の値を持つピボットテーブル
pivot_multi = df_sample.pivot_table(
values=['sales', 'price'],
index='region',
columns='product',
aggfunc={'sales': 'sum', 'price': 'mean'},
fill_value=0
)
print("複数値ピボットテーブル:")
print(pivot_multi.round(2))
print()
# 集計機能付きピボットテーブル
pivot_with_totals = df_sample.pivot_table(
values='sales',
index='region',
columns='product',
aggfunc='sum',
fill_value=0,
margins=True, # 合計行・列を追加
margins_name='総計'
)
print("合計付きピボットテーブル:")
print(pivot_with_totals)
時系列データの処理
日付データの操作
# 時系列データの処理
# 日付インデックスの設定
df_timeseries = df_sample.copy()
df_timeseries['date'] = pd.to_datetime(df_timeseries['date'])
df_timeseries = df_timeseries.set_index('date')
print("時系列データ:")
print(df_timeseries.head())
print()
# 日付コンポーネントの抽出
df_timeseries['year'] = df_timeseries.index.year
df_timeseries['month'] = df_timeseries.index.month
df_timeseries['day'] = df_timeseries.index.day
df_timeseries['weekday'] = df_timeseries.index.day_name()
print("日付コンポーネント:")
print(df_timeseries[['year', 'month', 'day', 'weekday']].head())
print()
# 期間での絞り込み
january_data = df_timeseries['2024-01']
print(f"1月のデータ: {len(january_data)} 行")
リサンプリングと集計
# リサンプリング(時間単位の変更)
# 日次データを週次に集計
weekly_sales = df_timeseries.resample('W')['sales'].agg(['sum', 'mean', 'count'])
print("週次集計:")
print(weekly_sales.head())
print()
# 月次集計
monthly_stats = df_timeseries.resample('M').agg({
'sales': ['sum', 'mean', 'count'],
'price': 'mean'
}).round(2)
print("月次統計:")
print(monthly_stats)
移動平均とローリング計算
# ローリング計算
# 移動平均
df_timeseries['sales_ma7'] = df_timeseries['sales'].rolling(window=7).mean()
df_timeseries['sales_ma30'] = df_timeseries['sales'].rolling(window=30).mean()
print("移動平均:")
print(df_timeseries[['sales', 'sales_ma7', 'sales_ma30']].head(10))
print()
# その他のローリング統計
df_timeseries['sales_rolling_std'] = df_timeseries['sales'].rolling(window=7).std()
df_timeseries['sales_rolling_max'] = df_timeseries['sales'].rolling(window=7).max()
print("ローリング統計:")
print(df_timeseries[['sales', 'sales_rolling_std', 'sales_rolling_max']].head(10))
実践的なデータ分析例
売上データ分析システム
class SalesAnalyzer:
"""売上データ分析システム"""
def __init__(self, df):
self.df = df.copy()
self.prepare_data()
def prepare_data(self):
"""データの前処理"""
# 日付変換
if 'date' in self.df.columns:
self.df['date'] = pd.to_datetime(self.df['date'])
# 売上金額を計算
if 'sales' in self.df.columns and 'price' in self.df.columns:
self.df['revenue'] = self.df['sales'] * self.df['price']
# 日付コンポーネントの追加
if 'date' in self.df.columns:
self.df['year'] = self.df['date'].dt.year
self.df['month'] = self.df['date'].dt.month
self.df['weekday'] = self.df['date'].dt.day_name()
def summary_report(self):
"""サマリーレポート生成"""
report = {}
# 基本統計
report['基本統計'] = {
'総売上': self.df['revenue'].sum(),
'平均売上': self.df['revenue'].mean(),
'売上件数': len(self.df),
'期間': f"{self.df['date'].min().date()} ~ {self.df['date'].max().date()}"
}
# 商品別分析
product_analysis = self.df.groupby('product').agg({
'sales': 'sum',
'revenue': 'sum',
'price': 'mean'
}).round(2)
product_analysis['revenue_share'] = (
product_analysis['revenue'] / product_analysis['revenue'].sum() * 100
).round(2)
report['商品別分析'] = product_analysis.sort_values('revenue', ascending=False)
# 地域別分析
region_analysis = self.df.groupby('region').agg({
'sales': 'sum',
'revenue': 'sum'
}).round(2)
region_analysis['revenue_share'] = (
region_analysis['revenue'] / region_analysis['revenue'].sum() * 100
).round(2)
report['地域別分析'] = region_analysis.sort_values('revenue', ascending=False)
return report
def generate_insights(self):
"""洞察の生成"""
insights = []
# 売上トップ商品
top_product = self.df.groupby('product')['revenue'].sum().idxmax()
insights.append(f"最も売上の高い商品: {top_product}")
# 売上トップ地域
top_region = self.df.groupby('region')['revenue'].sum().idxmax()
insights.append(f"最も売上の高い地域: {top_region}")
# 曜日別の傾向
weekday_sales = self.df.groupby('weekday')['revenue'].mean()
best_weekday = weekday_sales.idxmax()
insights.append(f"最も売上の良い曜日: {best_weekday}")
# 価格と売上の関係
correlation = self.df['price'].corr(self.df['sales'])
if correlation > 0.3:
insights.append("価格と売上に正の相関があります(高価格商品ほど良く売れる)")
elif correlation < -0.3:
insights.append("価格と売上に負の相関があります(低価格商品ほど良く売れる)")
else:
insights.append("価格と売上の相関は弱いです")
return insights
# 分析の実行
analyzer = SalesAnalyzer(df_sample)
print("=" * 60)
print("売上分析レポート")
print("=" * 60)
report = analyzer.summary_report()
print("n【基本統計】")
for key, value in report['基本統計'].items():
if isinstance(value, (int, float)):
print(f"{key}: {value:,.0f}")
else:
print(f"{key}: {value}")
print("n【商品別分析】")
print(report['商品別分析'])
print("n【地域別分析】")
print(report['地域別分析'])
print("n【主要な洞察】")
insights = analyzer.generate_insights()
for i, insight in enumerate(insights, 1):
print(f"{i}. {insight}")
重要なクラス・メソッドリファレンス
pandas.DataFrame クラス
データ分析の中核となるDataFrameの主要メソッドをカテゴリ別に整理しました。
import pandas as pd
import numpy as np
# DataFrame作成・情報取得
df_methods_info = {
# 基本情報
"df.shape": "行数・列数の取得 (行, 列)",
"df.info()": "データ型・メモリ使用量・欠損値情報",
"df.describe()": "数値列の基本統計量(平均・標準偏差等)",
"df.head(n)": "先頭n行を表示(デフォルト5行)",
"df.tail(n)": "末尾n行を表示(デフォルト5行)",
"df.sample(n)": "ランダムにn行をサンプリング",
# 列・インデックス情報
"df.columns": "列名一覧を取得",
"df.index": "インデックス一覧を取得",
"df.dtypes": "各列のデータ型を取得",
"df.memory_usage()": "メモリ使用量を詳細表示"
}
print("DataFrame基本情報取得メソッド:")
for method, description in df_methods_info.items():
print(f" {method:<25} # {description}")
データ選択・フィルタリング
# データ選択メソッド
selection_methods = {
# 列選択
"df['列名']": "単一列選択(Seriesとして返却)",
"df[['列1', '列2']]": "複数列選択(DataFrameとして返却)",
"df.select_dtypes(include=['number'])": "データ型による列選択",
"df.filter(regex='^売上')": "正規表現による列名マッチング",
# 行選択
"df.iloc[0:5, 1:3]": "位置ベース選択(行・列のインデックス番号)",
"df.loc['2024-01':'2024-12', '売上']": "ラベルベース選択(行・列名指定)",
"df.at[0, '列名']": "単一セルの高速アクセス",
"df.iat[0, 1]": "位置ベース単一セルアクセス",
# 条件フィルタリング
"df[df['売上'] > 1000]": "単一条件フィルタリング",
"df[(df['売上'] > 1000) & (df['地域'] == '東京')]": "複数条件フィルタリング(AND)",
"df.query('売上 > 1000 and 地域 == "東京"')": "SQL風条件指定",
"df.nlargest(5, '売上')": "指定列の上位n件取得",
"df.nsmallest(5, '売上')": "指定列の下位n件取得"
}
print("nデータ選択・フィルタリングメソッド:")
for method, description in selection_methods.items():
print(f" {method:<45} # {description}")
データ操作・変換
# データ操作メソッド
operation_methods = {
# 行・列操作
"df.drop(columns=['列名'])": "列の削除",
"df.drop(index=[0, 1])": "行の削除(インデックス指定)",
"df.rename(columns={'旧名': '新名'})": "列名変更",
"df.reset_index(drop=True)": "インデックスリセット",
"df.set_index('列名')": "指定列をインデックスに設定",
# データ変換
"df.astype({'列名': 'int32'})": "データ型変換",
"df.replace({'旧値': '新値'})": "値の置換",
"df.map({'A': 1, 'B': 2})": "Series値のマッピング変換",
"df.apply(lambda x: x*2)": "関数適用(列単位)",
"df.applymap(lambda x: str(x).upper())": "全要素に関数適用",
# 新列作成
"df.assign(新列=df['A'] + df['B'])": "新列追加(メソッドチェーン対応)",
"df.eval('新列 = A + B')": "式評価による新列作成(高速)"
}
print("nデータ操作・変換メソッド:")
for method, description in operation_methods.items():
print(f" {method:<40} # {description}")
データクリーニング
# データクリーニングメソッド
cleaning_methods = {
# 欠損値処理
"df.isnull()": "欠損値の検出(True/False)",
"df.isnull().sum()": "列ごとの欠損値数カウント",
"df.dropna()": "欠損値を含む行を削除",
"df.dropna(subset=['列名'])": "指定列の欠損値がある行を削除",
"df.fillna(value)": "欠損値を指定値で埋める",
"df.fillna(method='ffill')": "前の値で欠損値を埋める",
"df.fillna(method='bfill')": "後の値で欠損値を埋める",
"df.interpolate()": "線形補間で欠損値を埋める",
# 重複処理
"df.duplicated()": "重複行の検出",
"df.drop_duplicates()": "重複行の削除",
"df.drop_duplicates(subset=['列名'])": "指定列での重複削除",
# 異常値処理
"df.clip(lower=0, upper=100)": "値の範囲制限",
"df[df['列名'].between(10, 90)]": "範囲内データの抽出"
}
print("nデータクリーニングメソッド:")
for method, description in cleaning_methods.items():
print(f" {method:<35} # {description}")
集計・統計分析
# 集計・統計メソッド
aggregation_methods = {
# 基本統計
"df.mean()": "平均値計算",
"df.median()": "中央値計算",
"df.mode()": "最頻値計算",
"df.std()": "標準偏差計算",
"df.var()": "分散計算",
"df.min() / df.max()": "最小値・最大値",
"df.sum()": "合計値計算",
"df.count()": "非欠損値数カウント",
"df.quantile([0.25, 0.5, 0.75])": "パーセンタイル計算",
# 相関・共分散
"df.corr()": "相関係数行列計算",
"df.cov()": "共分散行列計算",
"df.corrwith(other_series)": "他のSeriesとの相関",
# GroupBy集計
"df.groupby('列名').agg({'列名': ['sum', 'mean']})": "グループ別複数統計量",
"df.groupby('列名').transform('mean')": "グループ統計量を元サイズで返却",
"df.groupby('列名').apply(custom_function)": "グループ別カスタム関数適用",
# ピボットテーブル
"df.pivot_table(values, index, columns, aggfunc)": "ピボットテーブル作成",
"df.crosstab(df['列1'], df['列2'])": "クロス集計表作成"
}
print("n集計・統計分析メソッド:")
for method, description in aggregation_methods.items():
print(f" {method:<50} # {description}")
ファイルI/O操作
# ファイル入出力メソッド
io_methods = {
# 読み込み
"pd.read_csv('file.csv', encoding='utf-8-sig')": "CSV読み込み(日本語対応)",
"pd.read_excel('file.xlsx', sheet_name=None)": "Excel読み込み(全シート)",
"pd.read_json('file.json')": "JSON読み込み",
"pd.read_sql(sql, connection)": "SQLデータベース読み込み",
"pd.read_parquet('file.parquet')": "Parquet読み込み(高速)",
# 保存
"df.to_csv('output.csv', index=False, encoding='utf-8-sig')": "CSV保存",
"df.to_excel('output.xlsx', sheet_name='シート1', index=False)": "Excel保存",
"df.to_json('output.json', orient='records')": "JSON保存",
"df.to_sql('table_name', connection, if_exists='replace')": "SQLデータベース保存",
"df.to_parquet('output.parquet')": "Parquet保存(高速)",
# 読み込みオプション
"pd.read_csv(usecols=['列1', '列2'])": "必要列のみ読み込み",
"pd.read_csv(dtype={'列名': 'category'})": "データ型指定読み込み",
"pd.read_csv(parse_dates=['日付列'])": "日付列自動変換",
"pd.read_csv(chunksize=10000)": "大容量ファイルの分割読み込み"
}
print("nファイルI/O操作メソッド:")
for method, description in io_methods.items():
print(f" {method:<55} # {description}")
時系列データ処理
# 時系列処理メソッド
timeseries_methods = {
# 日付変換・操作
"pd.to_datetime(df['日付列'])": "文字列を日付型に変換",
"pd.date_range('2024-01-01', periods=365, freq='D')": "日付範囲生成",
"df.set_index('date')": "日付列をインデックスに設定",
"df.index.year / .month / .day": "日付コンポーネント抽出",
"df.index.dayofweek": "曜日番号取得(月曜=0)",
"df.index.day_name()": "曜日名取得",
# 期間選択
"df['2024']": "年での絞り込み",
"df['2024-01']": "年月での絞り込み",
"df['2024-01-01':'2024-12-31']": "期間範囲での絞り込み",
# リサンプリング
"df.resample('M').sum()": "月次集計",
"df.resample('W').mean()": "週次平均",
"df.resample('Q').agg({'列名': ['sum', 'mean']})": "四半期集計",
# ローリング計算
"df.rolling(window=7).mean()": "7日移動平均",
"df.rolling(window=30).std()": "30日移動標準偏差",
"df.expanding().sum()": "累積合計",
"df.ewm(span=10).mean()": "指数加重移動平均"
}
print("n時系列データ処理メソッド:")
for method, description in timeseries_methods.items():
print(f" {method:<50} # {description}")
データ結合・マージ
# データ結合メソッド
merge_methods = {
# DataFrame結合
"pd.concat([df1, df2], axis=0)": "縦方向結合(行の追加)",
"pd.concat([df1, df2], axis=1)": "横方向結合(列の追加)",
"pd.concat([df1, df2], ignore_index=True)": "インデックスリセット結合",
# SQL風結合
"pd.merge(df1, df2, on='共通列')": "内部結合(INNER JOIN)",
"pd.merge(df1, df2, how='left', on='列名')": "左外部結合(LEFT JOIN)",
"pd.merge(df1, df2, how='right', on='列名')": "右外部結合(RIGHT JOIN)",
"pd.merge(df1, df2, how='outer', on='列名')": "完全外部結合(FULL OUTER JOIN)",
"pd.merge(df1, df2, left_on='列1', right_on='列2')": "異なる列名での結合",
# インデックス結合
"df1.join(df2, how='left')": "インデックスベース結合",
"df1.join(df2, lsuffix='_left', rsuffix='_right')": "同名列の接尾辞指定"
}
print("nデータ結合・マージメソッド:")
for method, description in merge_methods.items():
print(f" {method:<50} # {description}")
パフォーマンス最適化のコツ
# パフォーマンス最適化
performance_tips = {
# メモリ最適化
"df.astype('category')": "カテゴリ型でメモリ削減",
"df.astype('int32')": "小さい整数型でメモリ削減",
"pd.read_csv(dtype={'列名': 'category'})": "読み込み時型指定",
# 高速化テクニック
"df.eval('新列 = A + B')": "数値演算の高速化",
"df.query('A > 100')": "フィルタリングの高速化",
"df.loc[mask, '列名'] = value": "条件付き代入の高速化",
"df.values": "NumPy配列として取得(計算高速化)",
# ベクトル化操作
"df['列名'].map(辞書)": "マッピング変換(高速)",
"df['列名'].str.contains('パターン')": "文字列操作のベクトル化",
"df['列名'].dt.year": "日付操作のベクトル化",
# チャンクサイズ処理
"for chunk in pd.read_csv(chunksize=10000)": "大容量ファイルの分割処理"
}
print("nパフォーマンス最適化のコツ:")
for method, description in performance_tips.items():
print(f" {method:<45} # {description}")
実践的な使用パターン
class PandasBestPractices:
"""Pandas使用のベストプラクティス集"""
@staticmethod
def efficient_data_loading(file_path):
"""効率的なデータ読み込み"""
# 必要列のみ、適切な型で読み込み
df = pd.read_csv(
file_path,
usecols=['日付', '商品', '売上', '地域'], # 必要列のみ
dtype={
'商品': 'category', # カテゴリ型でメモリ削減
'地域': 'category',
'売上': 'float32' # 精度と速度のバランス
},
parse_dates=['日付'], # 日付自動変換
encoding='utf-8-sig'
)
return df
@staticmethod
def method_chaining_example(df):
"""メソッドチェーンの活用例"""
result = (df
.dropna(subset=['売上']) # 欠損値除去
.query('売上 > 0') # 正の売上のみ
.assign(売上カテゴリ=lambda x: pd.cut(x['売上'],
bins=[0, 1000, 5000, float('inf')],
labels=['低', '中', '高']))
.groupby(['地域', '売上カテゴリ']) # グループ化
.agg({'売上': ['sum', 'count']}) # 集計
.round(2)) # 小数点処理
return result
@staticmethod
def memory_optimization(df):
"""メモリ使用量最適化"""
# 数値列の最適化
for col in df.select_dtypes(include=['int64']).columns:
if df[col].min() >= 0 and df[col].max() <= 255:
df[col] = df[col].astype('uint8')
elif df[col].min() >= -128 and df[col].max() <= 127:
df[col] = df[col].astype('int8')
# 文字列列のカテゴリ化
for col in df.select_dtypes(include=['object']).columns:
if df[col].nunique() / len(df) < 0.5: # ユニーク率50%未満
df[col] = df[col].astype('category')
return df
# 使用例
print("n実践的な使用パターン:")
print("1. efficient_data_loading() - 効率的なデータ読み込み")
print("2. method_chaining_example() - メソッドチェーンの活用")
print("3. memory_optimization() - メモリ使用量最適化")
まとめとベストプラクティス
Pandas使用時のベストプラクティス
データ読み込み:
- 必要な列のみ読み込む(usecols パラメータ)
- 適切なデータ型を指定(dtype パラメータ)
- 大きなファイルはchunksizeで分割読み込み
メモリ管理:
- 不要なデータフレームは del で削除
- カテゴリ型を積極的に使用
- float64 より float32 を検討
操作の効率化:
- ループを避けてベクトル化操作を使用
- 複数の条件は query() で読みやすく
- chain method で可読性向上
データ品質:
- 定期的な欠損値チェック
- 重複データの確認と処理
- データ型の一貫性確保
次のステップ
- 高度な分析手法: 機械学習ライブラリとの連携
- ビッグデータ処理: Dask、Polarsなどの活用
- データベース連携: SQLAlchemyとの組み合わせ
- 可視化の強化: Plotly、Bokehなどの活用
関連記事
Pandasをマスターすることで、データ分析の世界が大きく広がります。まずは基本操作から始めて、徐々に高度な機能を身につけていきましょう。実際のプロジェクトで使いながら覚えることが、上達への近道です。
データ分析を深める: