Pandasの行と列の追加と削除など

スポンサーリンク
スポンサーリンク

行の追加

空のデータフレームに行を追加

カラム名を後で設定するか、初めに設定するかで追加の手順が変わります。
多分ですが、前者の方が処理速度は早いと思います。

カラム名もないデータフレームに追加

df = df.append(リスト型データ, ignore_index=True)

  • appendで空のデータフレームに追加して代入します。
  • その後、必要に応じてカラム名を設定します。
    df.columns = columns
columns = ["aaa", "bbb", "ccc"]

df = pd.DataFrame()
print(df)
# Empty DataFrame
# Columns: []
# Index: []
    
df = df.append([[1,2,3],[4,5,6]], ignore_index=True)
df.columns = columns
print(df)
#   aaa bbb ccc
# 0   1   2   3
# 1   4   5   6

カラム名だけあるデータフレームに追加

  1. 追加するデータで新規にデータフレームを作成します。
    df2 = pd.DataFrame(リスト型データ columns=columns)
  2. appendで新たなデータフレームを追加して代入します。
    df = df.append(新たなデータフレーム, ignore_index=True)
columns = ["aaa", "bbb", "ccc"]

df = pd.DataFrame(columns = columns)
print(df)
# Empty DataFrame
# Columns: [aaa, bbb, ccc]
# Index: []
    
df2 = pd.DataFrame([[1,2,3],[4,5,6]], columns=columns)

df = df.append(df2, ignore_index=True)
print(df)
#   aaa bbb ccc
# 0   1   2   3
# 1   4   5   6

行の末尾に追加

行名を指定して

atを用いて新規の行ラベル(インデックス)のみを指定し、リスト型またはタプル型の値を代入します。

df = pd.DataFrame([[1,2,3],[4,5,6]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2"])

# ラベルで指定
df.at['val3'] = [7, 8, 9]
print(df)
#       aaa  bbb  ccc
# val1  1.0  2.0  3.0
# val2  4.0  5.0  6.0
# val3  7.0  8.0  9.0
locilocでも取得できます。

行名を指定しない

df = pd.DataFrame([[1,2,3],[4,5,6]], columns = ["aaa", "bbb", "ccc"])
print(df)
#    aaa  bbb  ccc
# 0    1    2    3
# 1    4    5    6


print(df.append({"aaa": 7, "bbb": 8, "ccc": 9}, ignore_index=True))
#    aaa  bbb  ccc
# 0    1    2    3
# 1    4    5    6
# 2    7    8    9

行の先頭に追加

私の知る限り方法はありません。ただし、マージ(結合)という方法を取れば可能です。
もしくは、インデックスを用いてソートで表示順を指定する方法もあります。

行の指定の位置に追加(挿入)

私の知る限り方法はありません。
Pandasはデータベースの考え方に似ていますので、最後尾に追加後に、インデックスを用いてソートで表示順を指定する方法があります。

列の追加

列の末尾に追加

df = pd.DataFrame([[1,2,3],[4,5,6]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2"])
print(df)
#       aaa  bbb  ccc
# val1    1    2    3
# val2    4    5    6

# ラベルで指定
df['ddd'] = [7, 8]
print(df)
#       aaa  bbb  ccc  ddd
# val1    1    2    3    7
# val2    4    5    6    8
行数が一致していないとエラーになるので注意しましょう。

列の先頭、または任意の位置に追加

df.insert(列の位置, 追加する新しいカラム名, 値)で追加できます。

df = pd.DataFrame([[1,2,3],[4,5,6]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2"])
print(df)
#       aaa  bbb  ccc
# val1    1    2    3
# val2    4    5    6

# ラベルで指定
df.insert(0, 'ddd', [7, 8])
print(df)
#       aaa  bbb  ccc  ddd
# val1    1    2    3    7
# val2    4    5    6    8
列数をオーバーするとエラーになるので、注意しましょう。

別の列の値をずらして追加

このずらして追加は投資やディープラーニングでよく使います。例えばループで、毎回、前の行の値を取得するより、予め前の行の値を別の列に追加しておいた方が処理速度が格段に速くなります。

df.カラム名.shift(数値)

数値はデフォルトが1で1つ下にずれます。−1の場合は1つ上にずれます。

df = pd.DataFrame([[1,2,3],[4,5,6],[7, 8, 9]], columns = ["aaa", "bbb", "ccc"])
print(df)
#    aaa  bbb  ccc
# 0    1    2    3
# 1    4    5    6
# 2    7    8    9

df["ddd"] = df.ccc.shift()
print(df)
#    aaa  bbb  ccc  ddd
# 0    1    2    3  NaN
# 1    4    5    6  3.0
# 2    7    8    9  6.0

df["ddd"] = df.ccc.shift(-1)
print(df)
#    aaa  bbb  ccc  ddd
# 0    1    2    3  6.0
# 1    4    5    6  9.0
# 2    7    8    9  NaN

期間などの複数行の最大値などの値の列を追加

rolling(x).max()を使用します。

  • xに対象となる行数を入力します。
  • 対象には自身の行も含まれます。
  • xにマイナスを指定することはできません。列を追加後にshift()するといいです。
  • max以外に、mincountmeanmedianなどを利用できます。
    以下の公式サイトを参照してください。
    Window — pandas 2.1.0 documentation
  • idxmax()使用できません
  • それ以外に独自の関数を作成することが可能です。次の項目を確認してください。
import pandas as pd

df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns = ["aaa", "bbb", "ccc"]) # リスト型のデータで作成
print(df)
#    aaa  bbb  ccc
# 0    1    2    3
# 1    4    5    6
# 2    7    8    9

print(df["ccc"].max())
print(df["ccc"].idxmax())

df["ddd"] = df["ccc"].rolling(2).max()
print(df)
#    aaa  bbb  ccc  ddd
# 0    1    2    3  NaN
# 1    4    5    6  6.0
# 2    7    8    9  9.0

rollingで独自の関数を使用する

rolling(x).apply(y)を使用します。

  • xは同様にローリングする行数です。
  • yに独自に作成した関数名を設定します。
import pandas as pd

df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns = ["aaa", "bbb", "ccc"]) # リスト型のデータで作成
print(df)
#    aaa  bbb  ccc
# 0    1    2    3
# 1    4    5    6
# 2    7    8    9


def x(n):    
    return n.sum()*2

df["eee"] = df["ccc"].rolling(2).apply(x)
print(df)
#    aaa  bbb  ccc  ddd   eee
# 0    1    2    3  NaN   NaN
# 1    4    5    6  6.0  18.0
# 2    7    8    9  9.0  30.0
案外便利なので覚えておくと良いですね。

条件式で個別の値を列に追加

これも投資やディープラーニングでよく使います。ディープラーニングではしきい値を丸めたり正解ラベルを作成したりと、とっても便利です。

特に新しい関数はないのですが、ポイントは2つあります。

  • df.loc[条件式, 新しいカラム名] = 挿入する値
    これで条件に応じて、挿入する値を振り分けることができます。
  • 条件式のところで、~を使うと、その条件を除くという意味になります。わざわざ逆の条件式を書かなくて良いです。

今回は2つだけですが、いくつでも作ることができます。条件に満たない場合は、nanになります。

df = pd.DataFrame([[1,2,3],[4,5,6],[7, 8, 9]], columns = ["aaa", "bbb", "ccc"])
print(df)
#    aaa  bbb  ccc
# 0    1    2    3
# 1    4    5    6
# 2    7    8    9

mask = df['aaa'] > 1
column_name = 'ddd'

df.loc[mask, column_name] = 1
df.loc[~mask, column_name] = 0
print(df)
#    aaa  bbb  ccc  ddd
# 0    1    2    3  0.0
# 1    4    5    6  1.0
# 2    7    8    9  1.0

日時データの列から年月日、曜日などの列を追加

基本

df = pd.DataFrame([["2020/05/01 12:34:56",1,True],["2020/05/01 16:34:56",4,False]], columns = ["Date Time", "bbb", "ccc"]) # リスト型のデータで作成
df['Date Time']  = pd.to_datetime(df['Date Time'])

print(df)
#             Date Time  bbb    ccc
# 0 2020-05-01 12:34:56    1   True
# 1 2020-05-01 16:34:56    4  False

df['week'] = df['Date Time'].dt.weekday_name
print(df)
#             Date Time  bbb    ccc    week
# 0 2020-05-01 12:34:56    1   True  Friday
# 1 2020-05-01 16:34:56    4  False  Friday
dtはPandasのdtです。datetimeではありません。
元データは日時型でないとダメです。他にも以下を指定できます。
年月日(year, month, day
時分秒(hour, minute, second
曜日(文字列: weekday_name, 数値: dayofweek

他の方法

例えば「Friday」ではなく「Fri」としたい場合は以下のようにフォーマットを指定します。
また年月などの組み合わせも簡単に指定できます。

df = pd.DataFrame([["2020/05/01 12:34:56",1,True],["2020/05/01 16:34:56",4,False]], columns = ["Date Time", "bbb", "ccc"]) # リスト型のデータで作成
df['Date Time']  = pd.to_datetime(df['Date Time'])

print(df)
#             Date Time  bbb    ccc
# 0 2020-05-01 12:34:56    1   True
# 1 2020-05-01 16:34:56    4  False

df['week'] = df['Date Time'].dt.strftime('%a')

print(df)
#             Date Time  bbb    ccc week
# 0 2020-05-01 12:34:56    1   True  Fri
# 1 2020-05-01 16:34:56    4  False  Fri
dtはPandasのdtです。datetimeではありません。
元データは日時型でないとダメです。その他にも年月日などの列を作ることができます。フォーマットは以下のドキュメントを参照してください。
8.1. datetime --- 基本的な日付型および時間型 — Python 3.6.15 ドキュメント

削除

任意の列を削除

dropdelの二通りの方法がありますが、列の削除は、delの方が簡単で覚えやすいと思います。

df = pd.DataFrame([[1,2,3],[4,5,6]], columns = ["aaa", "bbb", "ccc"])
print(df)
#    aaa  bbb  ccc
# 0    1    2    3
# 1    4    5    6

# カラム名で指定
df = df.drop("bbb", axis = 1)

print(df)
#    aaa  ccc
# 0    1    3
# 1    4    6

del df["ccc"]
print(df)
#    aaa
# 0    1
# 1    4
列を削除する場合は、第二引数にaxis = 1と指定してください。
df = df.drop(カラム名, axis = 1)
dropで削除した際は、必ず元のDataframeに代入することを忘れないようにしましょう。
もしくはinplace=Trueと指定すれば代入は不要になりますが、覚える必要はないでしょう。列番号でも指定できますが、列番号で指定できるのはカラム名が設定されていない場合のみです。

任意の行を削除

df = pd.DataFrame([[1,2,3],[4,5,6]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2"])

# インデックス(ラベル)で指定
df = df.drop("val1")
print(df)
#       aaa  bbb  ccc
# val2    4    5    6


df = pd.DataFrame([[1,2,3],[4,5,6]], columns = ["aaa", "bbb", "ccc"])

# 行番で指定 
df = df.drop(0)
print(df)
#    aaa  bbb  ccc
# 1    4    5    6

 

dropで削除した際は、必ず元のDataframeに代入することを忘れないようにしましょう。
もしくはinplace=Trueと指定すれば代入は不要になりますが、覚える必要はないでしょう。
行番で指定できるのはインデックスが設定されていない場合のみ、列番号で指定できるのはカラム名が設定されていない場合のみです。

日付を指定して削除

df = pd.DataFrame([["2020/05/01",1,True],["2020/05/02",4,False]], columns = ["Date Time", "bbb", "ccc"])
df.index = pd.DatetimeIndex(pd.to_datetime(df['Date Time']), name='Date Time')
del df["Date Time"]

print(df.drop(pd.to_datetime("2020-05-01")))
# Date Time             
# 2020-05-02    4  False

上記は日時データに対しては使用できません。
その場合は以下で対応しています。(他に方法があるかもしれませんが。。

#                      bbb    ccc
# Date Time                      
# 2020-05-01 12:34:56    1   True
# 2020-05-02 16:34:56    4  False
        
import datetime as dt
df['days'] = df.index
df['days'] = df.days.dt.strftime('%m-%d')
df = df[df['days'] != "05-01"]
del df['days']

print(df)
# Date Time                      
# 2020-05-02 16:34:56    4  False

import datetime as dtを忘れないようにしましょう。

上記の方法では月と日を指定していますので、毎年1月1日などの削除が可能です。
すべての日曜日のデータを削除する場合は、以下のようにするといいです。

df['week'] = df['Date Time'].dt.strftime('%a')
df = df[df['week'] != "Sun"]

日付のその他の書式化コードはドキュメントを参照してください。
https://docs.python.org/ja/3.6/library/datetime.html#strftime-and-strptime-behavior

任意の複数行・列を削除

dropを使用します。受け渡す値をリスト形式にします。なお列を削除するdelは複数列に対応していません。

df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2", "val3"]) 

# ラベルで指定
df = df.drop(["val1", "val2"])
print(df)
#       aaa  bbb  ccc
# val3    7    8    9


df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns = ["aaa", "bbb", "ccc"]) # リスト型のデータで作成

# 行番で指定 
df = df.drop([0, 1])
print(df)
#    aaa  bbb  ccc
# 2    7    8    9

列を削除する場合は、第二引数にaxis = 1と指定してください。

範囲指定で行を削除

df = pd.DataFrame([[1,2,3],[4,None,6],[None,None,None],[7,8,9]], columns = ["aaa", "bbb", "ccc"]) 

df = df.drop(range(1, 3)) 
print(df)
#    aaa  bbb  ccc
# 0  1.0  2.0  3.0
# 3  7.0  8.0  9.0
この場合、インデックスが指定されていると使用できません

最後の行を削除

特に方法がありませんので、スライスを使用しましょう。

df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2", "val3"]) 

df = df[:-1]
print(df)
#       aaa  bbb  ccc
# val1    1    2    3
# val2    4    5    6


df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns = ["aaa", "bbb", "ccc"]) # リスト型のデータで作成

df = df[:-1]
print(df)
#       aaa  bbb  ccc
# val1    1    2    3
# val2    4    5    6
最初の行を削除する際にも、df = df[1:]とすれば削除できます。その方が便利な時が多いです。

条件による行の削除

df = pd.DataFrame([[1,2,3],[4,5,6],[None,None,None]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2", "val3"]) 

df = df.drop(df[(df.aaa == 1)].index) 
print(df)
#       aaa  bbb  ccc
# val2  4.0  5.0  6.0
# val3  NaN  NaN  NaN

少しデータベースっぽくなってきましたね。

条件式のところですが、PythonのIF文と異なるところがありとても重要です。
&|~を使う。
・条件毎にカッコ()で囲む。

空の値を削除

同じ条件でも空の値(Nan)は以下のようにします。

df = pd.DataFrame([[1,2,3],[4,None,6],[None,None,None]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2", "val3"]) 
print(df)
#       aaa  bbb  ccc
# val1  1.0  2.0  3.0
# val2  4.0  NaN  6.0
# val3  NaN  NaN  NaN


# 列を指定
df = df.drop(df[(df.bbb.isna())].index) 
print(df)
#       aaa  bbb  ccc
# val1  1.0  2.0  3.0

# nanが含まれる行を削除
print(df.dropna(how='any'))
#       aaa  bbb  ccc
# val1  1.0  2.0  3.0

# すべての値がnanである行を削除
print(df.dropna(how='all'))
#       aaa  bbb  ccc
# val1  1.0  2.0  3.0
# val2  4.0  NaN  6.0
列を指定する場合、isnullでも同じですが、isnaのエイリアスなのです。

行や列の順序を入れ替え

df.reindexで行や列の順番を並び替えることができます。

行の順番を入れ替え

df = pd.DataFrame([[1,2,3],[4,5,6]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2"])
print(df)
#       aaa  bbb  ccc
# val1    1    2    3
# val2    4    5    6

df = df.reindex(index=["val2", "val1"])
print(df)
#       aaa  bbb  ccc
# val2    4    5    6
# val1    1    2    3

列の順番を入れ替え

df = pd.DataFrame([[1,2,3],[4,5,6]], columns = ["aaa", "bbb", "ccc"], index = ["val1", "val2"])
print(df)
#       aaa  bbb  ccc
# val1    1    2    3
# val2    4    5    6

df = df.reindex(columns=["ccc", "aaa", "bbb"])
print(df)
#       ccc  aaa  bbb
# val1    3    1    2
# val2    6    4    5

 

コメント

タイトルとURLをコピーしました