Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Pandas クックブック

一般的な pandas のパターンと、それに対応する DataStore での書き方を紹介します。ほとんどのコードはそのまま動作します!

データの読み込み

CSVを読み込む

# Pandas
import pandas as pd

df = pd.read_csv("data.csv")

# DataStore - 同じです!
from chdb import datastore as pd
df = pd.read_csv("data.csv")

複数のファイルを読み込む

# Pandas
import glob

dfs = [pd.read_csv(f) for f in glob.glob("data/*.csv")]
df = pd.concat(dfs)

# DataStore - glob パターンを使用したより効率的な方法
df = pd.read_csv("data/*.csv")

フィルタリング

1つの条件

# Pandas と DataStore - 同一
df[df['age'] > 25]
df[df['city'] == 'NYC']
df[df['name'].str.contains('John')]

複数条件

# AND
df[(df['age'] > 25) & (df['city'] == 'NYC')]

# OR
df[(df['age'] < 18) | (df['age'] > 65)]

# NOT
df[~(df['status'] == 'inactive')]

query() を使用する

# Pandas と DataStore - 同一
df.query('age > 25 and city == "NYC"')
df.query('salary > 50000')

isin()

# Pandas と DataStore - 同一
df[df['city'].isin(['NYC', 'LA', 'SF'])]

between()

# Pandas と DataStore - 同一
df[df['age'].between(18, 65)]

カラムの選択

1つのカラム

# Pandas と DataStore - 同一
df['name']
df.name  # 属性アクセス

複数カラム

# Pandas と DataStore - 同一
df[['name', 'age', 'city']]

選択とフィルタ

# Pandas と DataStore - 同一
df[df['age'] > 25][['name', 'salary']]

# DataStore は SQL スタイルもサポート
df.filter(df['age'] > 25).select('name', 'salary')

ソート

単一カラム

# Pandas と DataStore - 同一
df.sort_values('salary')
df.sort_values('salary', ascending=False)

複数のカラム

# Pandas と DataStore - 同一
df.sort_values(['city', 'salary'], ascending=[True, False])

上位/下位 N を取得

# Pandas と DataStore - 同一
df.nlargest(10, 'salary')
df.nsmallest(5, 'age')

GroupBy と集計

基本的なGroupBy

# Pandas と DataStore - 同一
df.groupby('city')['salary'].mean()
df.groupby('city')['salary'].sum()
df.groupby('city').size()  # カウント

複数の集計

# Pandas と DataStore - 同一
df.groupby('city')['salary'].agg(['sum', 'mean', 'count'])

df.groupby('city').agg({
    'salary': ['sum', 'mean'],
    'age': ['min', 'max']
})

名前付き集計

# Pandas と DataStore - 同一
df.groupby('city').agg(
    total_salary=('salary', 'sum'),
    avg_salary=('salary', 'mean'),
    employee_count=('id', 'count')
)

複数の GroupBy キー

# Pandas と DataStore - 同一
df.groupby(['city', 'department'])['salary'].mean()

データの結合

内部結合

# Pandas
pd.merge(df1, df2, on='id')

# DataStore - 同じAPI
pd.merge(df1, df2, on='id')

# DataStore でもサポート
df1.join(df2, on='id')

左外部結合

# Pandas と DataStore - 同一
pd.merge(df1, df2, on='id', how='left')

異なるカラムでJOIN

# Pandas と DataStore - 同一
pd.merge(df1, df2, left_on='emp_id', right_on='id')

連結

# Pandas と DataStore - 同一
pd.concat([df1, df2, df3])
pd.concat([df1, df2], axis=1)

文字列操作

大文字・小文字変換

# Pandas と DataStore - 同一
df['name'].str.upper()
df['name'].str.lower()
df['name'].str.title()

部分文字列

# Pandas と DataStore - 同一
df['name'].str[:3]        # 最初の3文字
df['name'].str.slice(0, 3)
# Pandas と DataStore - 同一
df['name'].str.contains('John')
df['name'].str.startswith('A')
df['name'].str.endswith('son')

Replace

# Pandas と DataStore - 同一
df['text'].str.replace('old', 'new')
df['text'].str.replace(r'\d+', '', regex=True)  # 数字を削除

分割

# Pandas と DataStore - 同一
df['name'].str.split(' ')
df['name'].str.split(' ', expand=True)

長さ

# Pandas と DataStore - 同一
df['name'].str.len()

DateTime の演算

部分の抽出

# Pandas と DataStore - 同一
df['date'].dt.year
df['date'].dt.month
df['date'].dt.day
df['date'].dt.dayofweek
df['date'].dt.hour

フォーマット

# Pandas と DataStore - 同一
df['date'].dt.strftime('%Y-%m-%d')

欠損データ

欠損値の確認

# Pandas と DataStore では同じ
df['col'].isna()
df['col'].notna()
df.isna().sum()

欠損値を除外

# Pandas と DataStore - 同一
df.dropna()
df.dropna(subset=['col1', 'col2'])

欠損値の補完

# Pandas と DataStore - 同一
df.fillna(0)
df.fillna({'col1': 0, 'col2': 'Unknown'})
df.fillna(method='ffill')

新しいカラムを作成する

基本的な代入

# Pandas と DataStore - 同一
df['total'] = df['price'] * df['quantity']
df['age_group'] = df['age'] // 10 * 10

assign() を使用する

# Pandas と DataStore - 同一
df = df.assign(
    total=df['price'] * df['quantity'],
    is_adult=df['age'] >= 18
)

条件処理 (where/mask)

# Pandas と DataStore は同一
df['status'] = df['age'].where(df['age'] >= 18, 'minor')

カスタムロジック用の apply()

# 動作しますが、pandas の実行がトリガーされます
df['category'] = df['amount'].apply(lambda x: 'high' if x > 1000 else 'low')

# DataStore の代替手段(遅延実行のまま)
df['category'] = (
    df.when(df['amount'] > 1000, 'high')
      .otherwise('low')
)

整形

ピボットテーブル

# Pandas と DataStore - 同一
df.pivot_table(
    values='amount',
    index='region',
    columns='product',
    aggfunc='sum'
)

Melt (アンピボット)

# Pandas と DataStore は同じ
df.melt(
    id_vars=['name'],
    value_vars=['score1', 'score2', 'score3'],
    var_name='test',
    value_name='score'
)

Explode

# PandasとDataStore - 同一
df.explode('tags')  # 配列カラムを展開

ウィンドウ関数

移動

# Pandas と DataStore - 同一
df['rolling_avg'] = df['price'].rolling(window=7).mean()
df['rolling_sum'] = df['amount'].rolling(window=30).sum()

拡大

# Pandas と DataStore - 同一
df['cumsum'] = df['amount'].expanding().sum()
df['cummax'] = df['amount'].expanding().max()

Shift

# Pandas と DataStore - 同一
df['prev_value'] = df['value'].shift(1)   # ラグ
df['next_value'] = df['value'].shift(-1)  # リード

差分

# Pandas と DataStore - 同一
df['change'] = df['value'].diff()
df['pct_change'] = df['value'].pct_change()

出力

CSV形式

# Pandas と DataStore - 同一
df.to_csv("output.csv", index=False)

Parquet に出力

# PandasとDataStore - 同一
df.to_parquet("output.parquet")

pandas DataFrame に変換

# DataStore 固有
pandas_df = ds.to_df()
pandas_df = ds.to_pandas()

DataStore の拡張機能

SQLを表示

# DataStoreのみ
print(ds.to_sql())

実行計画の確認

# DataStore のみ
ds.explain()

ClickHouse の関数

# DataStore のみ - 追加アクセサ
df['domain'] = df['url'].url.domain()
df['json_value'] = df['data'].json.get_string('key')
df['ip_valid'] = df['ip'].ip.is_ipv4_string()

ユニバーサルURI

# DataStore のみ - どこからでも読み取り可能
ds = DataStore.uri("s3://bucket/data.parquet")
ds = DataStore.uri("mysql://user:pass@host/db/table")
Navigation