一覧へ

Pandasで実験データを整理する

Pandas DataFrameでCSV実験データを読み込み、フィルタリングし、グループ別統計を求める方法。

中級
|
90
|
検証済み (2026-06)
pandasDataFrameCSVデータ整理groupbymerge
進捗0/12 (0%)

Pandasで実験データを整理する

このトピックを終えたら

Pandas DataFrameでCSVを読み込み、条件付きフィルタリングを行い、グループ別統計を求め、2つのテーブルを結合できるようになります。


Pandasとは

前のトピックでcsvモジュールでファイルを読んでループで処理する方法を学びました。サンプル10個なら十分ですが、サンプルが5,000個でカラムが50個となるとループでは大変です。

Pandasは表形式データを扱うPythonライブラリです。Excelシートに似たDataFrame構造にデータを入れて、フィルタリング/ソート/集計を1行で処理します。

実験ノートで例えると — csvモジュールがノートを1行ずつ読むのに対して、Pandasは表全体を一目で広げて、欲しい列/行をすぐに取り出すことです。

DataFrameを作る

python
import pandas as pd
df = pd.read_csv("expression_data.csv")
print(df)
print(f"\n行: {len(df)}, 列: {len(df.columns)}")
print(f"カラム: {list(df.columns)}")

pd.read_csv()1行でCSVファイルがDataFrameになります。csv.DictReaderとループなしで全データがロードされます。

直接データを作ることもできます:

python
import pandas as pd
data = {
"sample_id": ["S001", "S002", "S003", "S004", "S005"],
"gene": ["EGFR", "TP53", "EGFR", "BRCA1", "TP53"],
"expression": [12.5, 3.2, 18.7, 7.1, 2.8],
"status": ["high", "low", "high", "medium", "low"],
}
df = pd.DataFrame(data)
print(df)

出力:

text
sample_id   gene  expression  status
0      S001   EGFR        12.5    high
1      S002   TP53         3.2     low
2      S003   EGFR        18.7    high
3      S004  BRCA1         7.1  medium
4      S005   TP53         2.8     low

データを眺める

DataFrameを初めて受け取ったら、全体像を素早く把握します:

python
df.head() # 先頭5行
df.tail(3) # 末尾3行
df.shape # (行数, 列数)
df.dtypes # 各列のデータ型
df.describe() # 数値列の基本統計(平均、標準偏差、最小値、最大値)

df.describe()は実験結果を初めて受け取った時、「大体どんな範囲か?」を把握するのに便利です。

列/行の選択

python
# 列を1つ選択 — Seriesを返す
genes = df["gene"]
# 複数の列を選択 — DataFrameを返す
subset = df[["sample_id", "expression"]]
# 行を選択 — インデックスで
first_row = df.iloc[0] # 最初の行
first_three = df.iloc[0:3] # 0〜2番目の行

条件付きフィルタリング

Pandasの核心機能です。csvモジュールでfor文+if文でやっていたことを1行にまとめます:

python
# EGFR遺伝子のみ
egfr = df[df["gene"] == "EGFR"]
print(egfr)
# expressionが5以上のサンプル
high_expr = df[df["expression"] >= 5.0]
print(high_expr)
# 複合条件:EGFRかつexpression >= 15
egfr_high = df[(df["gene"] == "EGFR") & (df["expression"] >= 15.0)]
print(egfr_high)
assert len(egfr) == 2
assert len(egfr_high) == 1

&はAND、|はOR。各条件を括弧で囲む必要があります。

ソート

python
# expressionの降順
sorted_df = df.sort_values("expression", ascending=False)
print(sorted_df)

グループ別集計:groupby

「遺伝子別の平均発現量は?」— Excelでピボットテーブルでやっていたことをgroupbyで行います:

python
gene_stats = df.groupby("gene")["expression"].agg(["mean", "std", "count"])
print(gene_stats)

出力:

text
mean       std  count
gene
BRCA1   7.10       NaN      1
EGFR   15.60  4.384062      2
TP53    3.00  0.282843      2

groupby("gene") — 遺伝子別にグループ化し、["expression"] — expression列に対して、agg(["mean", "std", "count"]) — 平均、標準偏差、個数を一度に計算します。

新しい列を追加

python
# expressionをlog2変換した列を追加
import numpy as np
df["log2_expression"] = np.log2(df["expression"])
print(df[["sample_id", "expression", "log2_expression"]])

2つのテーブルを結合する:merge

実験データとサンプル情報が別々のファイルにある場合:

python
import pandas as pd
# サンプルメタデータ
metadata = pd.DataFrame({
"sample_id": ["S001", "S002", "S003", "S004", "S005"],
"tissue": ["lung", "breast", "lung", "breast", "colon"],
"age": [45, 62, 38, 55, 71],
})
# expressionデータと結合
merged = pd.merge(df, metadata, on="sample_id")
print(merged)

on="sample_id" — 両テーブルで同じ値を持つ行同士を結合します。SQLのJOINと同じ概念です。database-basicsトピックで学んだことがここでも通用します。

結果を保存

python
# CSVとして保存
egfr.to_csv("egfr_samples.csv", index=False)
# TSVとして保存
egfr.to_csv("egfr_samples.tsv", sep="\t", index=False)

index=False — 行番号(0, 1, 2...)をファイルに含めません。

やってみよう(Faded Example)

空欄を埋めて、DataFrameで条件付きフィルタリングとグループ集計を行ってください。

穴埋め問題python
import pandas as pd
df = pd.read_csv("samples.csv")
# ODが1.0以上のサンプルをフィルタリング
passed = df[df["od"] 1.0]
# ステータス別平均OD
stats = df.("status")["od"].mean()
print(stats)

よくあるエラーと解決法

Q: KeyError: 'gene'が出ます

カラム名が正確か確認してください。df.columnsで実際のカラム名を出力してみてください。空白が含まれている可能性があります(" gene" vs "gene")。

Q: フィルタリングしたら空のDataFrameが返ってきます

条件が厳しすぎるか、データ型が合っていない可能性があります。df["expression"].dtypeで型を確認してください。文字列と数値を比較すると結果がないことがあります。

Q: SettingWithCopyWarningの警告が出ます

フィルタリングした結果に値を代入する時に出る警告です。df_filtered = df[条件].copy()で明示的なコピーを作ってから修正すれば警告が消えます。

Q: mergeしたら行数が増えました

onで指定した列に重複値があると、すべての組み合わせが作られて行が増えます。merge前に両方のテーブルでdf["sample_id"].duplicated().sum()で重複を確認してください。

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...