私はこのように見えるパンダデータフレームを持っています(それはかなり大きいものです)
date exer exp ifor mat
1092 2014-03-17 American M 528.205 2014-04-19
1093 2014-03-17 American M 528.205 2014-04-19
1094 2014-03-17 American M 528.205 2014-04-19
1095 2014-03-17 American M 528.205 2014-04-19
1096 2014-03-17 American M 528.205 2014-05-17
今、私は行ごとに繰り返したいと思います、そして私が各行を通過するとき、各行のifor
の値はいくつかの条件によって変わる可能性があり、私は別のデータフレームを検索する必要があります。
それでは、繰り返してこれを更新するにはどうすればよいですか。それらのどれも働かなかった少数の事を試みた。
for i, row in df.iterrows():
if <something>:
row['ifor'] = x
else:
row['ifor'] = y
df.ix[i]['ifor'] = x
これらのアプローチはどれもうまくいかないようです。データフレーム内で値が更新されていません。
Df.set_valueを使ってループ内で値を代入することができます。
for i, row in df.iterrows():
ifor_val = something
if <condition>:
ifor_val = something_else
df.set_value(i,'ifor',ifor_val)
行の値が必要ない場合は、dfのインデックスに対して単純に反復できますが、ここに示されていないものに行の値が必要な場合に備えて、元のforループを維持しました。
更新
df.set_value()はバージョン0.21.0から非推奨になりました。代わりにdf.at()を使うことができます。
for i, row in df.iterrows():
ifor_val = something
if <condition>:
ifor_val = something_else
df.at[i,'ifor'] = ifor_val
Pandas DataFrameオブジェクトは、Series of Seriesと見なす必要があります。言い換えれば、あなたはそれをコラムの観点から考えるべきです。これが重要なのは、pd.DataFrame.iterrows
を使用するときはSeriesとして行を反復処理しているからです。しかし、これらはデータフレームが保存しているシリーズではないではなく、繰り返している間に作成される新しいシリーズです。つまり、それらを割り当てようとしたときに、それらの編集内容が元のデータフレームに反映されることはありません。
わかりました、今それは邪魔にならないことです:私たちは何をしますか?
この記事の前に提案が含まれます:
pd.DataFrame.set_value
は Pandasバージョン0.21以降では非推奨ですpd.DataFrame.ix
は 推奨されなくなりましたpd.DataFrame.loc
は問題ありませんが、 は配列インデクサー に対して機能します。私のおすすめpd.DataFrame.at
を使用
for i in df.index:
if <something>:
df.at[i, 'ifor'] = x
else:
df.at[i, 'ifor'] = y
これを次のように変更することもできます。
for i in df.index:
df.at[i, 'ifor'] = x if <something> else y
if条件に前の行の値を使用する必要がある場合はどうなりますか?
for i in range(1, len(df) + 1):
j = df.columns.get_loc('ifor')
if <something>:
df.iat[i - 1, j] = x
else:
df.iat[i - 1, j] = y
使用できるメソッドは itertuples()
です。これは名前付きタプルとしてDataFrame行を繰り返し、タプルの最初の要素としてインデックス値を使用します。そしてそれはiterrows()
と比べてはるかに速いです。 itertuples()
の場合、各row
にはDataFrame内のIndex
が含まれており、loc
を使用して値を設定できます。
for row in df.itertuples():
if <something>:
df.at[row.Index, 'ifor'] = x
else:
df.at[row.Index, 'ifor'] = x
df.loc[row.Index, 'ifor'] = x
ありがとう@SantiStSupery、 .at
を使うほうがずっと速いです 。
df.ix[i, 'exp']=X
の代わりにdf.loc[i, 'exp']=X
またはdf.ix[i]['ifor'] = x
で値を代入する必要があります。
そうでなければ、あなたはビューに取り組んでおり、そして温暖化を受けるはずです:
-c:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead
しかし確かに、@Phillip Cloudが示唆しているように、DataFrame
を最大限に活用するには、ループを何らかのベクトル化されたアルゴリズムに置き換えるほうがよいでしょう。
とにかく、もしあなたがとにかくイテレートしようとしているのなら、どうしても最も単純な方法を使わないでください、df['Column'].values[i]
df['Column'] = ''
for i in range(len(df)):
df['Column'].values[i] = something/update/new_value
または、新しい値を古い値などと比較したい場合は、それをリストに格納してから最後に追加してください。
mylist, df['Column'] = [], ''
for <condition>:
mylist.append(something/update/new_value)
df['Column'] = mylist
for i, row in df.iterrows():
if <something>:
df.at[i, 'ifor'] = x
else:
df.at[i, 'ifor'] = y
列からMAX番号を増やします。例えば :
df1 = [sort_ID, Column1,Column2]
print(df1)
私の出力:
Sort_ID Column1 Column2
12 a e
45 b f
65 c g
78 d h
MAX = df1['Sort_ID'].max() #This returns my Max Number
それでは、df2に列を作成し、MAXを増分する列値を入力する必要があります。
Sort_ID Column1 Column2
79 a1 e1
80 b1 f1
81 c1 g1
82 d1 h1
注:df2は最初はColumn1とColumn2のみを含みます。 Sortid列を作成し、df1からMAXを増分する必要があります。