差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
次のリビジョン両方とも次のリビジョン
programming:python:packages:pandas:update_multi_column [2019/06/12] – [テーブル] ikatakosprogramming:python:packages:pandas:update_multi_column [2019/06/12] – [範囲の指定方法] ikatakos
行 3: 行 3:
 pandasは、DataFrameへのアクセス方法がいろいろあり、お世辞にも統一的とは言えないので、よく「この書き方でいいんだっけ」と混乱する。 pandasは、DataFrameへのアクセス方法がいろいろあり、お世辞にも統一的とは言えないので、よく「この書き方でいいんだっけ」と混乱する。
  
-基本は、以下サイトまとまっている。+基本的に(一般的な代入と同じく)左辺で更新するデータ範囲を右辺で値を指定する、左辺でデータ範囲の指定方法が様々あるのに加え、右辺での値の指定にも複数方法がある。
  
-  [[http://sinhrks.hatenablog.com/entry/2014/11/12/233216|Python pandas データ選択処理をちょっと詳しく <前編> - StatsFragments]]+  df.loc[df['col1']==3, ['col2', 'col3']] = df['col4']
  
 大別すると以下の感じ。 大別すると以下の感じ。
-左辺に例えば配列を渡しても、アクセス方法や配列の中身によって、名前か、添字か、boolか、どのように解釈されるか異なってくるのがややこしさの元となる。+左辺のアクセス関数に例えば配列を渡しても、関数の種類配列の中身によって、名前か、添字か、どのように解釈されるか異なってくるのがややこしさの元となる。
  
-  * 左辺のアクセス方法+  * 左辺のアクセス関数
     * ''%%.__getitem__%%''(''df[xxx]'' のような角括弧の記法)     * ''%%.__getitem__%%''(''df[xxx]'' のような角括弧の記法)
     * ''.loc''     * ''.loc''
     * ''.iloc''     * ''.iloc''
-  * 左辺のアクセスに指定できる値 +  * 左辺のアクセス関数の引数に指定できる値 
-    * 単一の名前 +    * 単一の名前単一の添字 
-    * 単一の添字 +    * 名前の配列添字の配列 
-    * 名前の配列 +    * 名前のslice添字のslice
-    * 添字の配列 +
-    * 名前のslice +
-    * 添字のslice+
     * 列数と同じ長さのbool配列     * 列数と同じ長さのbool配列
     * 行数と同じ長さのbool配列     * 行数と同じ長さのbool配列
     * DataFrame     * DataFrame
 +    * Series
   * 右辺の指定方法   * 右辺の指定方法
     * 単一の値     * 単一の値
行 31: 行 29:
  
 ''print(df)'' した時は、名前は表示されるが、添字は表示されない。 ''print(df)'' した時は、名前は表示されるが、添字は表示されない。
-また、添字は負の値で末尾から数えられるなど、通常の配列の添字と同じようなものである+また、添字は負の値で末尾から数えられるなど、通常の配列の添字と似た機能を持つ
  
                           1      2    ←列の添字                           1      2    ←列の添字
行 41: 行 39:
   行の添字 行の名前   行の添字 行の名前
  
-配列は numpy.ndarray や pandas.Series などでもよい。+配列は numpy.ndarray でもよい。
  
-====データ扱われ方====+====範囲指定==== 
 + 
 +データ範囲の指定方法は、以下のサイトがまとまっている。 
 + 
 +  * [[http://sinhrks.hatenablog.com/entry/2014/11/12/233216|Python pandas データ選択処理をちょっと詳しく <前編> - StatsFragments]] 
 + 
 +loc, ilocは基本 ''[行, 列]'' の順なのに比べ、getitemは時と場合でころころ変わりやがる。
  
 ^                                                                  |^  getitem                                                        ^  loc                                              ^  iloc                                         ^ ^                                                                  |^  getitem                                                        ^  loc                                              ^  iloc                                         ^
行 126: 行 130:
  
 </sxh> </sxh>
 +
 +=====代入値の指定方法=====
 +
 +FIXME
 +
 +
 =====SettingWithCopyWarning===== =====SettingWithCopyWarning=====
  
行 146: 行 156:
 # 1         5 # 1         5
  
-df.col1[df.col1 == 2] = 100  # OK+df['col1'][df['col1'== 2] = 100  # OK
  
-df[df.col1 == 2].col1 = 100  # SettingWithCopyWarning+df[df['col1'== 2]['col1'= 100  # SettingWithCopyWarning
  
-df.col1[df.col1 > 1][df.col1 < 3] = 100  # NG(特に警告も出ない)+df['col1'][df['col1'> 1][df['col1'< 3] = 100  # NG(特に警告も出ない)
  
-df.loc[df.col1 == 2, 'col1'] = 100  # OK+df.loc[df['col1'== 2, 'col1'] = 100  # OK
 </sxh> </sxh>
  
-''df.col1'' は、df中の1カラムのSeriesを返す。dfはこのSeriesを参照として持っているので、このSeriesに対する更新はdfにも反映される。Seriesに対して"''df.col1 == 2''"に合致する行を抽出し、結果に直接代入しているので、OK。+1番目の書き方、''df['col1']'' は、df中の1カラムのSeriesを返す。dfはこのSeriesを参照として持っているので、このSeriesに対する更新はdfにも反映される。Seriesに対して"''df['col1'== 2''"に合致する行を抽出し、結果に直接代入しているので、OK。
  
-''df[df.col1 == 2]'' は、まず"''df.col1 == 2''"に合致する行を抽出している。この時点で元のdfとは別物となっていて、''.col1''で取り出されるSeriesも、元のSeriesとは別物となる。それに対して更新しても、反映されない。+2番目の書き方、''df[df['col1'== 2]'' は、まず"''df['col1'== 2''"に合致する行を抽出している。この時点で元のdfとは別物となっていて、その後''['col1']''で取り出されるSeriesも、元のSeriesとは別物となる。それに対して更新しても、反映されない。
  
-3番目も同様。''df.col1[df.col1 > 1]'' までで別物となり、さらなる抽出結果に代入しても反映されない。+3番目も同様。''df['col1'][df['col1'> 1]'' までで別物となり、さらなる抽出結果に代入しても反映されない。
  
-''df.loc[]'' は行列の条件を一度に指定して抽出する方法で、抽出した物に直接代入しているのでOK。+4番目の''df.loc[]'' は行列の条件を一度に指定して抽出する方法で、これは1回の抽出結果に直接代入しているのでOK。
  
-pandasでは ''df[df.col1 == 2].col1 = 100'' のように、2回以上に分けて抽出した結果に何かを代入しても、元の''df''の値は置き換わらない。+pandasでは ''df[df['col1'== 2]['col1'= 100'' のように、2回以上に分けて抽出した結果に何かを代入しても、元の''df''の値は置き換わらない。
  
 こういうコードを書くと警告が出る。 こういうコードを書くと警告が出る。
行 177: 行 187:
   * [[https://linus-mk.hatenablog.com/entry/2019/02/02/200000|pandasのSettingWithCopyWarningを理解する (1/3) - 子供の落書き帳 Renaissance]]   * [[https://linus-mk.hatenablog.com/entry/2019/02/02/200000|pandasのSettingWithCopyWarningを理解する (1/3) - 子供の落書き帳 Renaissance]]
  
-上記を読めば後段の説明は不要なのだが、まぁ、せっかくだし残しておこう。+上記を読めば下記の回避方法の説明は不要なのだが、まぁ、せっかくだし残しておこう。
  
 ====回避方法==== ====回避方法====
行 198: 行 208:
 </sxh> </sxh>
  
-行と列を一度に指定してDataFrame内の要素を抽出する方法は、at, iat, loc, iloc がある。+行と列を一度に指定してDataFrame内の要素を抽出する方法は、loc, iloc がある。 
 +他にもatとかixとかあるが、柔軟に解釈してくれるおかげでさらに紛れが発生しやすいので、基本はこの2つだけ覚えておけばよい
  
   * [[https://note.nkmk.me/python-pandas-at-iat-loc-iloc/|pandasで任意の位置の値を取得・変更するat, iat, loc, iloc | note.nkmk.me]]   * [[https://note.nkmk.me/python-pandas-at-iat-loc-iloc/|pandasで任意の位置の値を取得・変更するat, iat, loc, iloc | note.nkmk.me]]
  
-===列はカラム名、行はindexで指定===+===列は名、行は添字で指定===
  
-<note> +locも列も前で指定する」、ilocは「も添字で指定する」のどちらかしか無く、「は名前で指定したいが、行は添字で指定したい」時に困る。
-「インデックス」DataFrameをprintした時に左にある行名(上の例だと100,200,300)、 +
-「indexが先頭か何番目(配添字と一緒、0,1,2)とする。 +
-</note>+
  
-loc「行も列も名称,インデックスで指定する」、ilocは「行も列もindexで指定する」のどちらしか無く、「列はカラム名で指定したいが、行はindexで指定したい」時に困る。+劇的な解決といが、以下の解決策がある。
  
-劇的な解決とはいかないが、「あらかじめ目的行のインデックスを調べてからlocを使う」または「あらかじめ目的列のindexを調べてからilocを使う」ことで回避できる。+  * あらかじめ目的行の名前を調べてからlocを使う 
 +  * あらかじめ目的列の添字を調べてからilocを使う
  
   * [[https://stackoverflow.com/questions/28754603/indexing-pandas-data-frames-integer-rows-named-columns|python - Indexing Pandas data frames: integer rows, named columns - Stack Overflow]]   * [[https://stackoverflow.com/questions/28754603/indexing-pandas-data-frames-integer-rows-named-columns|python - Indexing Pandas data frames: integer rows, named columns - Stack Overflow]]
  
 <sxh python> <sxh python>
-# あらかじめ目的行のインデックスを調べてからlocを使う +  名前で['col2', 'col3'] 列、添字で[1, 2]行目のデータを更新したい 
-rows = df.index[[1, 2]]  # 2,3行目のインデックスを得る + 
-df.loc[rows, ['col2', 'col3']] = 30  # locでインデックス指定 +# 【あらかじめ目的行の名前を調べてからlocを使う 
-print(df)+df.index                # df.indexで、行の名前の配列を取得 
 +=> [100  200  300] 
 +df.index[[1, 2]]        df.indexへの添字アクセスにより2,3行目の名前を得る 
 +# => [200  300] 
 +df.loc[df.index[[1, 2]], ['col2', 'col3']] = 30  # これをlocに用いること、目的が達成される 
 +df
 # => # =>
 #      col1  col2  col3 #      col1  col2  col3
行 227: 行 241:
  
  
-# あらかじめ目的列のindexを調べてからilocを使う +あらかじめ目的列のindexを調べてからilocを使う】 
-col2_idx = df.columns.get_loc('col2' # 'col2'のindexを得る+df.columns 
 +# => ['col1', 'col2', 'col3'           # df.columnsで、列の名前の配列を取得 
 +col2_idx = df.columns.get_loc('col2'   # 'col2', 'col3'のindexを得る
 col3_idx = df.columns.get_loc('col3') col3_idx = df.columns.get_loc('col3')
-df.iloc[[1, 2], [col2_idx, col3_idx]] = 40 + 
-print(df)+df.iloc[[1, 2], [col2_idx, col3_idx]] = 40  # これをilocに用いることで、目的が達成される 
 +df
 # => # =>
 #      col1  col2  col3 #      col1  col2  col3
programming/python/packages/pandas/update_multi_column.txt · 最終更新: 2021/12/03 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0