web-dev-qa-db-ja.com

行ごとに繰り返しながら、パンダのデータフレームを更新します。

私はこのように見えるパンダデータフレームを持っています(それはかなり大きいものです)

           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

これらのアプローチはどれもうまくいかないようです。データフレーム内で値が更新されていません。

139
AMM

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
147
rakke

Pandas DataFrameオブジェクトは、Series of Seriesと見なす必要があります。言い換えれば、あなたはそれをコラムの観点から考えるべきです。これが重要なのは、pd.DataFrame.iterrowsを使用するときはSeriesとして行を反復処理しているからです。しかし、これらはデータフレームが保存しているシリーズではないではなく、繰り返している間に作成される新しいシリーズです。つまり、それらを割り当てようとしたときに、それらの編集内容が元のデータフレームに反映されることはありません。

わかりました、今それは邪魔にならないことです:私たちは何をしますか?

この記事の前に提案が含まれます:

  1. pd.DataFrame.set_valuePandasバージョン0.21以降では非推奨です
  2. pd.DataFrame.ix推奨されなくなりました
  3. 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
46
piRSquared

使用できるメソッドは 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を使うほうがずっと速いです

19
GoingMyWay

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を最大限に活用するには、ループを何らかのベクトル化されたアルゴリズムに置き換えるほうがよいでしょう。

17
CT Zhu

とにかく、もしあなたがとにかくイテレートしようとしているのなら、どうしても最も単純な方法を使わないでください、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
7
Pranzell
for i, row in df.iterrows():
    if <something>:
        df.at[i, 'ifor'] = x
    else:
        df.at[i, 'ifor'] = y
5
Duane

列から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を増分する必要があります。

0
Shazir Jabbar