差分

この文書の現在のバージョンと選択したバージョンの差分を表示します。

この比較画面にリンクする

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
programming:python:packages:pandas:update_multi_column [2019/06/13]
ikatakos
programming:python:packages:pandas:update_multi_column [2019/06/26] (現在)
ikatakos [巨大なDFに対する更新はなるべく一度に]
ライン 1: ライン 1:
 ======DataFrameの値の更新 - pandas====== ======DataFrameの値の更新 - pandas======
  
-pandasは、DataFrameアクセス方法がいろいろあるため、値の取得・代入もよく「この書き方でいいんだっけ」と混乱する。+pandasは、DataFrameの値の取得方法がいろいろあるため、値の代入更新つい「この書き方でいいんだっけ」と混乱する。
  
 基本的には(一般的な代入と同じく)左辺で更新するデータ範囲を、右辺で値を指定するのだが、左辺のデータ範囲の指定方法が様々あるのに加え、右辺での値の指定にも複数方法がある。 基本的には(一般的な代入と同じく)左辺で更新するデータ範囲を、右辺で値を指定するのだが、左辺のデータ範囲の指定方法が様々あるのに加え、右辺での値の指定にも複数方法がある。
ライン 20: ライン 20:
     * 名前の配列、添字の配列     * 名前の配列、添字の配列
     * 名前のslice、添字のslice     * 名前のslice、添字のslice
-    * 列数と同じ長さのbool配列 +    * 列数と同じ長さのbool配列行数と同じ長さのbool配列
-    * 行数と同じ長さのbool配列+
     * DataFrame     * DataFrame
     * Series     * Series
ライン 28: ライン 27:
     * 左辺と同じサイズの配列     * 左辺と同じサイズの配列
  
-ここで、「名前」とは行や列に付けられた名称を差し、「添字」とは0から始まる連番(通常の配列の要素取得に使うもの)を指すものとする。+ここで、「名前」とは行や列に付けられた名称を差し、「添字」とは0から始まる連番(通常の配列の要素取得に使うもの)を指すものとする。
  
-''​print(df)''​ した時は、名前は表示されるが、添字は表示されない。 +配列は numpy.ndarray でもよい。
-また、添字は負の値で末尾から数えられるなど、通常の配列の添字と似た機能を持つ。 +
- +
-                     ​0 ​     1      2    ←列の添字 +
-                  col1   ​col2 ​  ​col3 ​   ←列の名前 +
-  0  2019/​01/​01 +
-  1  2019/​01/​08 +
-  2  2019/​01/​15 +
-  ↑         ↑ +
-  行の添字 行の名前 +
- +
-配列は numpy.ndarray でもよい。+
  
 ====範囲の指定方法==== ====範囲の指定方法====
ライン 49: ライン 37:
   * [[http://​sinhrks.hatenablog.com/​entry/​2014/​11/​12/​233216|Python pandas データ選択処理をちょっと詳しく <​前編>​ - StatsFragments]]   * [[http://​sinhrks.hatenablog.com/​entry/​2014/​11/​12/​233216|Python pandas データ選択処理をちょっと詳しく <​前編>​ - StatsFragments]]
  
-loc, ilocは原則 ''​[行,​ 列]''​ の順でlocが名前、ilocが添字として解釈されるため意味を明確にコーディングしたい場合はそちらを使うのが良い。+loc, ilocは法則性がありわかりやすい。原則 ''​loc[行, 列]''​ の順で指定する。(bool配列以外は)locが名前、ilocが添字として解釈される。 
 +意味を明確にコーディングしたい場合はこれらを使うのが良い。
  
-対してgetitemは、なんとなくよく使う方で解釈されるため、便利な反面、行なのか列なのか時と場合で変わり、紛らわしいので注意+対してgetitemは、なんとなくよく使う方で解釈されるため、便利な反面、行なのか列なのか時と場合で変わり、やや紛らわしい。
  
 ^                                                                  |^  getitem ​                                                       ^  loc                                              ^  iloc                                         ^ ^                                                                  |^  getitem ​                                                       ^  loc                                              ^  iloc                                         ^
ライン 389: ライン 378:
  
 但し、あるidに条件を満たすレコードが1つも無かった場合、そのidのカラムcはnanになる。 但し、あるidに条件を満たすレコードが1つも無かった場合、そのidのカラムcはnanになる。
 +
 +=====その他小ネタ=====
  
 ====inplaceは効かない==== ====inplaceは効かない====
ライン 416: ライン 407:
   * [[https://​stackoverflow.com/​questions/​43856701/​pandas-inplace-view-copy-confusion|python - Pandas - inplace, view, copy confusion - Stack Overflow]]   * [[https://​stackoverflow.com/​questions/​43856701/​pandas-inplace-view-copy-confusion|python - Pandas - inplace, view, copy confusion - Stack Overflow]]
   * [[https://​github.com/​pandas-dev/​pandas/​issues/​11984|Pandas replacing values on specific columns. view vs. copy · Issue #11984 · pandas-dev/​pandas · GitHub]]   * [[https://​github.com/​pandas-dev/​pandas/​issues/​11984|Pandas replacing values on specific columns. view vs. copy · Issue #11984 · pandas-dev/​pandas · GitHub]]
 +
 +
 +====巨大なDFに対する更新はなるべく一度に====
 +
 +数百~数千万行のDataFrameに対して更新をかけるのは、かなりコストの重い操作となる。たとえ更新する範囲が一部であっても、その場所の特定に時間がかかる。
 +
 +もし、groupby() などの分割結果毎に何らかの集計処理し、元のDFに結果を反映させたい場合でも、毎回、元のDFを更新していては相当時間がかかる。
 +(そもそもgroupbyごとにforループ回すのも速度的によろしいことではないが。。。関数的に書けない集計処理が必要になることもあるので仕方ない)
 +
 +そんな時、即時更新はせずリストに溜めて、更新は最後に(メモリが厳しいならある程度溜まった後に)行えば、高速化に繋がる。
 +
 +下記は一例だが、もっと速い方法もあるかも知れない。
 +
 +<sxh python>
 +# 非推奨
 +for i, grouped_df in df.groupby('​AAA'​):​
 +    # なんか処理する
 +    # 毎回、元のDFを更新する → 遅い
 +    df.loc[grouped_df.index,​ '​BBB'​] = grouped_df['​CCC'​]
 +
 +
 +# こっちの方が速い
 +buf = []
 +for i, grouped_df in df.groupby('​AAA'​):​
 +    # なんか処理する
 +    # とりあえずバッファに溜める
 +    buf.append(grouped_df['​CCC'​])
 +
 +# 最後に更新する
 +update_sr = pd.concat(buf)
 +update_sr.sort_index(inplace=True) ​ # indexは整列されてた方が速い
 +df.loc[update_sr.index,​ '​BBB'​] = update_sr
 +</​sxh>​
 +
  
  
programming/python/packages/pandas/update_multi_column.1560422449.txt.gz · 最終更新: 2019/06/13 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0