S-JIS[2018-02-18] 変更履歴

Python Pandas DataFrame

Pythonの拡張モジュールPandas(0.22.0)のDataFrameのメモ。


概要

DataFrameは表を表すクラス。2次元配列に列名(および行名)を付けたもの。

import pandas as pd

df = pd.DataFrame({
    "a": [1, 2, 3],
    "b": [4, 5, 6],
})

あるいは

from pandas import DataFrame

df = DataFrame({
    "a": [1, 2, 3],
    "b": [4, 5, 6],
})

DataFrameでは、列をcolumn、行をindexで表す。
(つまり列名はカラム名、行名はインデックス名ということになる)

df = DataFrame({
    "a": [1, 2, 3],
    "b": [4, 5, 6],
})
print(df.columns) #→ Index(['a', 'b'], dtype='object')
print(df.index)   #→ RangeIndex(start=0, stop=3, step=1)

DataFrameから列名を指定して1列分のデータを取り出すと、Seriesで返る。

s = df["a"]

生成方法

DataFrameを生成する例。

結果 説明
df = DataFrame({
    "a": [1, 2, 3],
    "b": [4, 5, 6],
})
  a b
0 1 4
1 2 5
2 3 6
Python標準のdict(キーがカラム名、値がリスト)を指定して生成する。
df = DataFrame({
    "a": [1, 2, 3],
    "b": [4, 5, 6],
}, columns=["a", "b"])
  a b
0 1 4
1 2 5
2 3 6
ただし、dictはキーの並び順が不定なので、指定した順序の表になるとは限らない。
columnsで列の順序を指定する事が出来る。
df = DataFrame([
    [11, 22, 33],
    [44, 55, 66],
])
  0 1 2
0 11 22 33
1 44 55 66
2次元配列(リスト)を指定すると、内側のリストが行データとなる。
df = DataFrame([
    [11, 22, 33],
    [44, 55, 66],
], columns=["a", "b", "c"])
  a b c
0 11 22 33
1 44 55 66
2次元配列(リスト)と共にcolumnsで列名を指定できる。
df = DataFrame(
    [1, 2, 3],
    columns=["a"]
)
  a
0 1
1 2
2 3
1次元配列(リスト)だと、1列の表になる。

操作

DataFrameの操作。

例の結果 説明 ビューかどうか
c = df.columns
Index(['a', 'b'], dtype='object')
カラム名(を保持するIndexオブジェクト)を取得する。
カラム名の変更
 
i = df.index
RangeIndex(start=0, stop=3, step=1)
インデックス名(行名)(を保持するIndexオブジェクト)を取得する。
インデックス名の変更
 
v = df.values
array([[1, 4],
       [2, 5],
       [3, 6]], dtype=int64)
値(NumPyのndarray)を取得する。 (コピー)
df.head(2)
  a b
0 1 4
1 2 5
先頭行のDataFrameを返す。
引数を省略した場合は5行。
ビュー
df.tail(2)
  a b
1 2 5
2 3 6
末尾行のDataFrameを返す。
引数を省略した場合は5行。
ビュー
df.describe()
  a b
count 3.0 3.0
mean 2.0 5.0
std 1.0 1.0
min 1.0 4.0
25% 1.5 4.5
50% 2.0 5.0
75% 2.5 5.5
max 3.0 6.0
統計データ(DataFrame)を返す。 コピー
df2 = df.copy()
  同じ内容のDataFrameを返す。 コピー
df2 = df.rename(columns={"a": "AA"})
  AA b
0 1 4
1 2 5
2 3 6
カラム名(列名)を変更したDataFrameを返す。

引数indexでインデックス名(行名)を変更できる。

コピー
t = df.T
  0 1 2
a 1 2 3
b 4 5 6
行と列を入れ替えたDataFrameを返す。 ビュー
# 行名でソート
s = df.sort_index(axis=0, ascending=False)
df.sort_index() は
df.sort_index(axis=0, ascending=True) と同じ
  a b
2 3 6
1 2 5
0 1 4
行名や列名でソートしたDataFrameを返す。 コピー
# 列名でソート
s = df.sort_index(axis=1, ascending=False)
  b a
0 4 1
1 5 2
2 6 3
s = df.sort_values(by="b", ascending=False)
  a b
2 3 6
1 2 5
0 1 4
列の値でソートしたDataFrameを返す。
by=["a", "b"]のようにして複数カラムを指定可能。
コピー
df = DataFrame({
    "a": [1, float("nan"), 3],
    "b": [4, 5, 6],
})
df2 = df.dropna()
  a b
0 1.0 4
2 3.0 6
NaNの行を削除したDataFrameを返す。 コピー
df = DataFrame({
    "a": [1, float("nan"), 3],
    "b": [4, 5, 6],
})
df2 = df.fillna(value=99)
  a b
0 1.0 4
1 99.0 5
2 3.0 6
NaNを“指定された値”に変換したDataFrameを返す。 コピー
df = DataFrame({
    "a": [1, float("nan"), 3],
    "b": [4, 5, 6],
})
b = pd.isna(df)
  a b
0 False False
1 True False
2 False False
NaNをTrue、それ以外をFalseとするDataFrameを返す。 コピー
left = DataFrame({
    "key": ['foo', 'bar', 'zzz', 'bar'],
    "lval": [1, 2, 3, 4],
})
right = DataFrame({
    "key": ['foo', 'bar'],
    "rval": [8, 9],
})
df = pd.merge(left, right, on="key", how="left")
left
  key lval
0 foo 1
1 bar 2
2 zzz 3
3 bar 4
right
  key rval
0 foo 8
1 bar 9

df
  key lval rval
0 foo 1 8.0
1 bar 2 9.0
2 zzz 3 NaN
3 bar 4 9.0
2つのDataFrameを結合する。
onで結合キーを指定する。
コピー
df = left.set_index("key").join(
    right.set_index("key"),
    how="left"
)
  lval rval
key    
bar 2 9.0
bar 4 9.0
foo 1 8.0
zzz 3 NaN
2つのDataFrameを結合する。
joinメソッドはインデックス名(行名)で結合する。
コピー

要素の操作

例の結果 説明 ビューかどうか
s = df["b"]
0    4
1    5
2    6
Name: b, dtype: int64
角括弧で列名を指定すると、1列分のデータ(Series)を返す。 ビュー
r = df[1:2]
  a b
1 2 5
角括弧でスライスを指定すると、その範囲の行データ(DataFrame)を返す。
l = df.loc[1:2, "a":"b"]
l = df.loc[[1, 2], ["a", "b"]]
  a b
1 2 5
2 3 6
locで行名(インデックス名)・列名(カラム名)の範囲を指定すると、その範囲のデータ(DataFrame)を返す。
この場合、範囲の終端に当たる名前のデータも含まれる。
名前のリストを渡すことも出来る。
ビュー
r1 = df.loc[1]
a    2
b    5
Name: 1, dtype: int64
locで行名(インデックス名)のみを指定すると、1行分のデータ(Series)を返す。
c1 = df.loc[:, "b"]
0    4
1    5
2    6
Name: b, dtype: int64
locで列名(カラム名)のみを指定すると、1列分のデータ(Series)を返す。
df.loc[0, "a"]
1
locで行名・列名のみを指定すると、1要素分のデータを返す。 (コピー)
i = df.iloc[1:2, 0:2]
  a b
1 2 5
ilocは行・列の番号(0オリジン)を指定する。
(スライスで指定した場合、通常のリストのスライスと同じく、終端のデータは含まれない)
ビュー
r1 = df.iloc[1]
a    2
b    5
Name: 1, dtype: int64
c1 = df.iloc[:, 1]
0    4
1    5
2    6
Name: b, dtype: int64
df.iloc[0, 0]
1
(コピー)
df.at[0, "a"]
1
atは1要素分のデータを返す。
locと同じだが、atでは範囲を指定した場合や結果が1要素にならない場合はエラーになる)
(コピー)
df.iat[0, 0]
1
iatは行・列の番号(0オリジン)を指定する。 (コピー)
df.at[0, "a"] = 99
# df["a"][0] = 99
  a b
0 99 4
1 2 5
2 3 6
値の変更。 (自身)
df["b"] = [100, 101, 102]
  a b
0 1 100
1 2 101
2 3 102
列(の値)の変更。
要素数がDataFrameの行数と一致していないとエラーになる。
(自身)
df["c"] = [100, 101, 102]
  a b c
0 1 4 100
1 2 5 101
2 3 6 102
列の追加。
新しい列名に代入すると追加になる。
(自身)
del df["a"]
  b
0 4
1 5
2 6
列の削除。 (自身)
d = {"a": 8, "b": 9}
df2 = df.append(d, ignore_index=True)
  a b
0 1 4
1 2 5
2 3 6
3 8 9
行を追加したDataFrameを返す。 コピー
df2 = df.drop(1)
  a b
0 1 4
2 3 6
行を削除したDataFrameを返す。
(インデックス名(行名)を指定する)
コピー

スカラー演算

DataFrameは数値(数学で言えばスカラー)と演算することが出来る。

df = DataFrame([[1, 2], [3, 4]], columns=["a", "b"])
df2 = df * 10

↓df2の結果

  a b
0 10 20
1 30 40

DataFrameの各要素との演算になる。


比較演算も行うことが出来る。

df = DataFrame([[1, 2], [3, 4]], columns=["a", "b"])
b = df >= 4

↓bの結果

  a b
0 False False
1 False True

比較演算の結果は、boolのDataFrameになる。

&, |~(not相当)も使うことが出来る。
ただし演算子の優先順位は==や>=より&,|の方が高いので、組み合わせる場合は注意。(比較演算の項を丸括弧で囲む 必要がある)

df = DataFrame([[1, 2], [3, 4]], columns=["a", "b"])
b = (df <= 1) | (df >= 4)

↓bの結果

  a b
0 True False
1 False True

boolのDataFrameを添字にするとTrueの箇所の要素だけ取り出せる。

df = DataFrame([[1, 2], [3, 4]], columns=["a", "b"])
b = (df <= 1) | (df >= 4)
df2 = df[b]
df = DataFrame([[1, 2], [3, 4]], columns=["a", "b"])

df2 = df[df % 2 == 0]
↓df2の結果 ↓df2の結果
  a b
0 1.0 NaN
1 NaN 4.0
  a b
0 NaN 2
1 NaN 4

→NaNはfillnaメソッドで変換できる


Pandasへ戻る / Pythonへ戻る / 技術メモへ戻る
メールの送信先:ひしだま