随時更新
DataFrame作成
データのみ指定
print(pd.DataFrame(data=[[0, 1, 2], [3, 4, 5]]))
# 0 1 2
# 0 0 1 2
# 1 3 4 5
列名を指定
df = pd.DataFrame(data=[[0, 1, 2], [3, 4, 5]], columns=["a", "b", "c"])
print(df)
# a b c
# 0 0 1 2
# 1 3 4 5
# dictでも良い
pd.DataFrame({"a": [1, 2], "b": [2, 3], "c": [3, 4]})
タイプはデータによって自動に設定される
print(df.dtypes)
# a int64
# b int64
# c int64
データタイプを指定する場合
ただし、列毎にタイプを指定することはできない
df = pd.DataFrame(data=[[1, 2, 3], [2, 3, 4]], columns=["a", "b", "c"], dtype="Int32")
print(df.dtypes)
# a int32
# b int32
# c int32
データタイプを列毎に指定する場合
df = pd.DataFrame(np.array([(1, 2, 3), (4, 5, 6)], dtype=[("a", "i1"), ("b", "i2"), ("c", "i4")]))
print(df.dtypes)
# a int8
# b int16
# c int32
forループ
基本的にpandasのループ処理は遅い
元のDataFrame
df = pd.DataFrame(np.arange(150).reshape((50, 3)), columns=["a", "b", "c"])
# a b c
# 0 0 1 2
# 1 3 4 5
# :
# 48 144 145 146
# 49 147 148 149
単純for
for d in df:
print(d)
# a
# b
# c
# 列名が表示されるだけなので、列名だけ取りたいなら以下で
print(df.columns.values)
# ['a' 'b' 'c']
items (列ループ)
列でループされ、列名と列のSeriesが取得される
for label, ser in df.items():
print(f"label : {label}")
print(f"series : {ser}")
# label : a
# series : 0 0
# 1 3
# :
# label : b
# series : 0 1
# 1 4
# :
# label : c
# series : 0 2
# 1 5
# :
iterrows (行ループ)
行でループされ、行indexと行のSeriesが取得される。
基本的に遅いのでitertuplesを使ったほうが良い
for index, row in df.iterrows():
print(f"index : {index}")
print(f"row : {row}")
# index : 0
# row : a 0
# b 1
# c 2
# Name: 0, dtype: int32
# index : 1
# row : a 3
# b 4
# c 5
# Name: 1, dtype: int32
# :
itertuples (行ループ)
行でループされ、名前付きのタプルが取得される。
基本的にはiterrowsより高速
for row in df.itertuples():
print(row)
# Pandas(Index=0, a=0, b=1, c=2)
# Pandas(Index=1, a=3, b=4, c=5)
# Pandas(Index=2, a=6, b=7, c=8)
# 引数無しの場合はPandasという名前のタプルになる。別名をつけたい場合は
for row in df.itertuples(name='No'):
print(row)
# No(Index=0, a=0, b=1, c=2)
# No(Index=1, a=3, b=4, c=5)
# No(Index=2, a=6, b=7, c=8)
列を指定して行ループ
DataFrameの列を指定してループする
itertuplesよりも高速
for row in df["a"]:
print(row)
# 0
# 3
# 6
# 複数列を指定するする場合はzipでまとめる
for row in zip(df["a"], df["b"], df["c"]):
print(row)
# (0, 1, 2)
# (3, 4, 5)
# (6, 7, 8)
ループ速度の話
参考値
# 5000行データ
df = pd.DataFrame(np.arange(15000).reshape((5000, 3)), columns=['a', 'b', 'c'])
# zip(df["a"], df["b"], df["c"])
837 µs ± 47.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# df.itertuples()
2.27 ms ± 49.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# df.iterrows()
95.4 ms ± 2.72 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
データ選択
元データ
df = pd.DataFrame(np.arange(9).reshape((3, 3)), columns=['C0', 'C1', 'C2'], index=['R0','R1','R2'])
print(df)
# C0 C1 C2
# R0 0 1 2
# R1 3 4 5
# R2 6 7 8
loc
ラベル名で行とか列の単位で取得する場合に使用する
# [index名]指定
# この場合はSeriesで取得
print(df.loc["R0"])
# C0 0
# C1 1
# C2 2
# Name: R0, dtype: int32
# [[行ラベル]]の複数指定。
# この場合はDataFrameで取得される
print(df.loc[["R0", "R2"]])
# C0 C1 C2
# R0 0 1 2
# R2 6 7 8
# [行ラベル:行ラベル]のスライス指定。
# この場合はDataFrameで取得される
print(df.loc["R0":"R2"])
# C0 C1 C2
# R0 0 1 2
# R1 3 4 5
# R2 6 7 8
# [行ラベル, 列ラベル]で指定
# loc[("R0", "C1")]でも同等だが基本使わないかと
print(df.loc["R0", "C1"])
# 1
# [[行ラベル], 列ラベル]のindex複数指定、単カラム指定。
# この場合はSeriesで取得
print(df.loc[["R0","R1"], "C0"])
# R0 0
# R1 3
Name: C0, dtype: int32
# [[行ラベル], [列ラベル]]のindex複数指定、単カラム指定。
# この場合はDataFrameで取得
print(df.loc[["R0","R1"], ["C0", "C1"]])
# C0 C1
# R0 0 1
# R1 3 4
# [行ラベル:行ラベル, 列ラベル:列ラベル]のスライス指定。
# この場合はDataFrameで取得
print(df.loc["R0":"R1", "C0":"C1"])
# C0 C1
# R0 0 1
# R1 3 4
# [[bool]]boolean指定。表示行を指定できる
# これを使って条件による絞込などを行う
print(df.loc[[True, False, True]])
# C0 C1 C2
# R0 0 1 2
# R2 6 7 8
# [[行表示bool], [列表示bool]]boolean指定。表示行、列を指定できる
print(df.loc[[True, False, True], [True, False, True]])
# C0 C2
# R0 0 2
# R2 6 8
iloc
位置番号で行とか列の単位で取得する場合に使用する。
番号で指定すること以外はlocとほぼ同じ。
print(df.iloc[0])
# C0 0
# C1 1
# C2 2
# Name: R0, dtype: int32
# マイナスでの取得も可能
print(df.iloc[-1])
# C0 6
# C1 7
# C2 8
# Name: R2, dtype: int32
# [2行目、1列目]を取得
print(df.iloc[1, 0])
# 3
at
行ラベル、列ラベルで一つの値を取得する場合に使用する。
一つの値の変更もこれを使う
# at[行ラベル、列ラベル]
# at[("R0", "C0")]でも同等だが基本使わないかと
print(df.at["R0", "C0"])
# 0
# 値を変更
df.at["R0", "C0"] = 9
print(df)
# C0 C1 C2
# R0 9 1 2
# R1 3 4 5
# R2 6 7 8
iat
位置番号で一つの値を取得する場合に使用する。
番号で指定すること以外はatとほぼ同じ。
# at[行ラベル、列ラベル]
# at[(0, 0)]でも同等だが基本使わないかと
print(df.at[0, 0])
# 0
# 値を変更
df.iat[0, 0] = 9
print(df)
# C0 C1 C2
# R0 9 1 2
# R1 3 4 5
# R2 6 7 8
C0列を取得
C0 | C1 | C2 | |
---|---|---|---|
R0 | 0 | 1 | 2 |
R1 | 3 | 4 | 5 |
R2 | 6 | 7 | 8 |
# df.C0と同等
print(df["C0"])
# R0 0
# R1 3
# R2 6
# Name: C0, dtype: int32
以下でも同じ。
このレベルの取得は[]のアクセスの方が高速
df.loc[:, "C0"]
df.iloc[:, 0]
1行目(index R0)を取得
C0 | C1 | C2 | |
---|---|---|---|
R0 | 0 | 1 | 2 |
R1 | 3 | 4 | 5 |
R2 | 6 | 7 | 8 |
# DataFrameで取得されるので注意
print(df[0:1])
# C0 C1 C2
# R0 0 1 2
以下でも取得できるが、Seriesで取得される
df.loc[0]
print(df.iloc[0])
# C0 0
# C1 1
# C2 2
# Name: R0, dtype: int32
C0列の1行目(index R0)を取得
C0 | C1 | C2 | |
---|---|---|---|
R0 | 0 | 1 | 2 |
R1 | 3 | 4 | 5 |
R2 | 6 | 7 | 8 |
print(df.at[0, "C0"])
# 0
以下でも同じ。
df.iat[0, 0]
locでも取得できるが、一つの値を取得するならatの方が早い
df.loc[0, "C0"]
また、以下の方法でも取得はできるがdataframe→series.locしているのでat,iatを普通は使う
df["C0"][0]
df["C0"][0:1] # ただし取得できるのはSeries
df["C0"].loc[0]
df["C0"].iloc[0]
ある列の値が条件に一致する行を取得
C0列が偶数の行を取得
C0 | C1 | C2 | |
---|---|---|---|
R0 | 0 | 1 | 2 |
R1 | 3 | 4 | 5 |
R2 | 6 | 7 | 8 |
print(df[df["C0"] % 2 == 0])
# C0 C1 C2
# R0 0 1 2
# R2 6 7 8
以下でも同様
df.query("C0 % 2 == 0")
df.loc[df['C0'] % 2 == 0]
df[df.apply(lambda row: row['C0'] % 2 == 0, axis=1)]
ある行の値が条件に一致する列を取得
R2行が偶数の列を取得
C0 | C1 | C2 | |
---|---|---|---|
R0 | 0 | 1 | 2 |
R1 | 3 | 4 | 5 |
R2 | 6 | 7 | 8 |
print(df.loc[:, df.loc['R2'] % 2 == 0])
# C0 C2
# R0 0 2
# R1 3 5
# R2 6 8
速度の話
※あくまで参考値
単一の値を取得する場合
atが最速
# 元データ
df = pd.DataFrame(np.arange(15000).reshape((5000, 3)), columns=['a', 'b', 'c'])
# df.at[2500, "b"]
5.11 µs ± 459 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
# df["b"][2500]
6.47 µs ± 883 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
# df.loc[2500, "b"]
10.3 µs ± 2.66 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
# df.iat[2500, 1]
19 µs ± 4.63 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
# df.iloc[2500, 1]
28.5 µs ± 8.42 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
列(or行)を取得する場合
[]が最速
# 元データ
df = pd.DataFrame(np.arange(15000).reshape((5000, 3)), columns=['a', 'b', 'c'], index=[str(i) for i in range(5000)])
# df["b"]
4.51 µs ± 1.21 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
# df.loc[:, "b"]
23.8 µs ± 5.62 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
# df.iloc[:, 1]
41.5 µs ± 9.62 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
条件に一致する行を取得する場合
[]とlocはほぼ同等。queryは遅い
# 元データ
df = pd.DataFrame(np.arange(9).reshape((3, 3)), columns=['C0', 'C1', 'C2'], index=['R0','R1','R2'])
# df.loc[df['C0'] % 2 == 0]
279 µs ± 45.2 µs per loop (mean ± std. dev. of 7 runs, 500 loops each)
# df[df["C0"] % 2 == 0]
249 µs ± 62.6 µs per loop (mean ± std. dev. of 7 runs, 500 loops each)
# df[df.apply(lambda row: row['C0'] % 2 == 0, axis=1)]
355 µs ± 51.5 µs per loop (mean ± std. dev. of 7 runs, 500 loops each)
# df.query("C0 % 2 == 0")
1.74 ms ± 158 µs per loop (mean ± std. dev. of 7 runs, 500 loops each)