Bus errorとSegmentation faultに困ったら見るブログ

物理の研究者による日々の研究生活のメモ書きです ( python/emacs/html/Japascript/シェルスクリプト/TeX/Mac/C言語/Linux/git/tmux/R/ポケモンGO)

【python3, pandas】csvで条件を満たす行を修正 + ある行をファイル末尾にコピーして追記

pythonのpandasでcsvを開いて、条件を満たす行に加工をする + ある行をファイル末尾にコピーして追記したい

pandasというのを使うのは初めてだった
・勝手にindexという列ができていたり、そのindexは加工不可だったりで色々と大変だった・・・
・astropyの単位みたいに、printしたら勝手にヘッダーにあるkeyも表示されてたりしてその対処が必要
・ある列、ある行の要素を取り出すのに、リストみたいに通し番号で指定できるのかと思ったらそれはできなかった・・・ ilocといかいうのを使う必要がある

import pandas as pd

df = pd.read_csv('hoge.csv')

fname="hoge.png"

# このcsvの中で、filenameという要素で"hoge.png"を含んでいる行を抽出する
print(df[df["filename"] == fname])

# もしその行の通し番号が欲しかったら
list(df[df["filename"] == fname].index)
# これで
# [13, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 134, 180]
# が手に入る

#
# filenameという要素がhoge.pngを含んでいる行のdateを更新する
# 頭にシャープをいれてコメントアウト(csvのコメントアウトの文字はないと思うけど、読み込めなくできればOKなので・・・)
#
ll = df[df["filename"] == fname]
line_to_add = ll.iloc[0].values
for i in list(ll.index):
 df.loc[df.index==i, ["date"]] = "#" + df.loc[df.index==i, ["date"]]

# ファイルの末尾に、ある行をコピーして追記する
n = len(df["aaa"])
df.loc[n] = line_to_add

# 追加した行の他の要素を修正する
df.loc[n, ["x"]] = 1111
df.loc[n, ["y"]] = 2222

# 修正後のdfをcsvとして保存する
df.to_csv('hoge.csv', index=False)

参考リンク

pd.read_csvはファイルを開いて、読み込んで、さらに閉じてくれるのでその後の処理が楽
pythonでのcsvファイルの読み込み #Python3 - Qiita


最初はpandasのreplaceでなんとかすればいいと思ったが、うまくいかなかった
pandas.DataFrame, Seriesの要素の値を置換するreplace | note.nkmk.me

                      • -

pandasで読み込んだcsvのindexをいじりたいとき用↓
df1 = df.set_index("filename")
とか
pandasでcsvの読み込みをしてIndexをいじってみる #Python - Qiita

pandas.DataFrameの列をインデックス(行名)に割り当てるset_index | note.nkmk.me

                      • -

いつか使うかも
これは便利そう
indexにdatatime型を指定すると、ある日付の範囲のデータのみを取り出す、とかがかんたんにできる
pandasのindexはdatetimeにすると便利 #Python - Qiita

                      • -

ファイル末尾に追加する方法について
最初はappendでやろうとしたが、うまくいかなかった

一応メモ↓
pandas.DataFrameに列や行を追加(assign, appendなど) | note.nkmk.me

今回は
n = len(df["gain"])
df.loc[n] = df[df.index==13].values[0]
みたいにして追加した

任意の位置の値を取得するには at, iat, loc, ilocを使う
今回はilocしか使ってないけど・・・
pandasで任意の位置の値を取得・変更するat, iat, loc, iloc | note.nkmk.me

ilocとかを使わずにdfをfor文に打ち込むと、warningが出る
chained indexingというらしい
pandas の SettingWithCopyWarning で苦労した話 #Python - Qiita

pandasのSettingWithCopyWarningの対処法 | note.nkmk.me

                      • -

修正したdfをcsvでもう一度書き出す方法
index=Falseを付けないと、indexという列が新しく追加されるので注意
あと、headerがいるかどうかも選べる
Pandasのto_csv関数を使ってCSVファイルに書き出す方法 - DeepAge

                      • -

data frameの仕様でハマったのでメモ

data frameの内容をコピーするのに = を使うと参照渡し(C言語のアドレス)みたいなことになって、単純な値をコピーすることにはならない
コピー元が修正されたら、=の左辺も置き換わってしまう(ここにハマった・・・)

(これは別にdata frameに限った話じゃなくてpythonもこういう仕様らしい、が今の所これで変なことが起こったことはないんだよなぁ・・ 謎)

単純な値のコピーをしたいなら、
hoge = df.copy(deep=True)

deepcopyというのは新しいidで作成されるので、新しい変数になる

ランキングに参加中、クリックにご協力お願いします!