質問するログイン新規登録
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

1回答

1008閲覧

SettingWithCopyWarningの解決方法について

tamtam2020

総合スコア1

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2024/03/06 12:50

0

0

実現したいこと

DataFrameの中の1列を取り出して、その移動平均を計算し、新たな列として加えたい。

発生している問題・分からないこと

SettingWithCopyWarningが発生します。(計算結果はあっているもよう)

エラーメッセージ

error

1<ipython-input-1-44eea35d0d69>:12: SettingWithCopyWarning: 2A value is trying to be set on a copy of a slice from a DataFrame. 3Try using .loc[row_indexer,col_indexer] = value instead 4 5See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy 6 df1['SMA1'] = df1['b'].rolling(2).mean() 7

該当のソースコード

import pandas as pd df = pd.DataFrame({'a': [0, 1, 2], 'b': [3, 4, 5], 'c':[6,7,8]}, index=['x', 'y', 'z']) print(df) print() df1 = df.iloc[:, [1]] print(df1) print() # rollingで移動平均を作る df1['SMA1'] = df1['b'].rolling(2).mean() print(df1)

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

DataFrameから1列抽出するのではなく、最初から1列だけの場合には、警告は出ません。

import pandas as pd

df2 = pd.DataFrame({'b': [3, 4, 5]}, index=['x', 'y', 'z'])
print(df2)
print()

rollingで移動平均線を作る

df2['SMA1'] = df2['b'].rolling(2).mean()

print(df2)

結果は以下の通り。
b
x 3
y 4
z 5

b SMA1
x 3 NaN
y 4 3.5
z 5 4.5

補足

できうるならば、最初のような形で、DataFrameから列を抽出して作業をしたいのですが、どのようにすればいいのか、教えていただけませんでしょうか。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2024/03/06 13:18 編集

warning message にある様に、loc メソッドを使うとよいかと。 df1.loc[:,['SMA1']] = df1['b'].rolling(2).mean()
tamtam2020

2024/03/06 13:29

ありがとうございます。でも、ダメでした。 <ipython-input-2-113a0d1e09c6>:14: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy df1.loc[:,['SMA1']] = df1['b'].rolling(2).mean()
melian

2024/03/06 13:38 編集

こちらの環境は Python 3.11.6/Pandas 2.2.1 なのですが、.loc メソッドを使うことで warning message が表示されなくなります。 もしくは、編集前のコメントに書いた様に df1 を作成する際に copy() を実行するとよいかもしれません。 df1 = df.iloc[:, [1]] => df1 = df.iloc[:, [1]].copy()
tamtam2020

2024/03/06 13:41

ありがとうございます。 バージョンの問題ですか、、、私が使っているのは、Google Colaboratoryですが、 バージョンは、 Python 3.10.12 Pandas 1.5.3 です。バージョンを上げれば警告は消えて、かつ問題ない、ということですかね。
melian

2024/03/06 13:44

> バージョンを上げれば警告は消えて、かつ問題ない、ということですかね。 はい、おそらくその通りかと。差し支えがなければ Pandas を最新版にアップデートしてみてください。
tamtam2020

2024/03/06 14:04

ありがとうございます。ですが、せっかくのご提案ながら、うまく行きません。 まず、Google Colabでのpandasのバージョンアップができません。dependency conflictsを生じているとか。何か、根本的に変えなければいけないのかもしれません。 また、.copy を付けると、以下のエラーが出ます。 TypeError: 'method' object is not subscriptable もう少し、調べてみます。
melian

2024/03/06 14:08

こちらでも試してみましたが、最初に Pandas 2.2.1 をインストールしてコードを実行すると warning は表示されませんでした。 !pip install pandas==2.2.1
tamtam2020

2024/03/06 14:16

ありがとうございます。しかし、なぜかうまく行きません。 !pip install pandas==2.2.1 の結果は、以下のエラーで、バージョンアップはされていません。 Collecting pandas==2.2.1 Using cached pandas-2.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (13.0 MB) Requirement already satisfied: numpy<2,>=1.22.4 in /usr/local/lib/python3.10/dist-packages (from pandas==2.2.1) (1.25.2) Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.10/dist-packages (from pandas==2.2.1) (2.8.2) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas==2.2.1) (2023.4) Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.10/dist-packages (from pandas==2.2.1) (2024.1) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.8.2->pandas==2.2.1) (1.16.0) Installing collected packages: pandas Attempting uninstall: pandas Found existing installation: pandas 2.1.4 Uninstalling pandas-2.1.4: Successfully uninstalled pandas-2.1.4 ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. bigframes 0.22.0 requires pandas<2.1.4,>=1.5.0, but you have pandas 2.2.1 which is incompatible. google-colab 1.0.0 requires pandas==1.5.3, but you have pandas 2.2.1 which is incompatible. Successfully installed pandas-2.2.1 何か、環境がことなるのでしょうか?
tamtam2020

2024/03/06 14:21

いや、ノートブックを新規作成し、そこでpandasをバージョンアップすると、できました。これで先に進めそうです。どうもありがとうございます。
melian

2024/03/06 14:22

一応、Successfully installed pandas-2.2.1 と表示されていますので、インストールはされている模様です。実際、コードの実行に支障はありませんでした。ただ、google-colab 1.0.0 と不整合を起こしているので、Pandas のアップデートはやめておく方がよいのかもしれません。 > また、.copy を付けると、以下のエラーが出ます。 > TypeError: 'method' object is not subscriptable copy() メソッドについて、 df1 = df.iloc[:, [1]].copy() としていますでしょうか?
tamtam2020

2024/03/06 14:26

どうもありがとうございます。おっしゃられる通りで、copy の後の () が抜けていました。入れると、うまく行きました。
bsdfan

2024/03/07 04:39

pandas のバージョンはあまり関係なく、df1 = df.iloc[:, [1]].copy() が正しい対処です。 df1 = df.iloc[:, [1]] df1['SMA1'] = ... は、プログラムの処理系にとっては、 df.iloc[:, [1]]['SMA1'] = ... をやろうとしているように見えなくもないため、SettingWithCopyWarning が発生しています。 データフレームから別のデータフレームを切り出したときは注意が必要です。(https://qiita.com/FukuharaYohei/items/b3aa7113d08858676910 とか読むと理解が深まるかと)
tamtam2020

2024/03/07 11:34

どうもありがとうございます。 .copy() で対応します。 ご紹介いただいたサイト、またそこからリンクが張られている徹底詳解3部作とか、一応見てみたのですが、ビューとコピーの違いもよくわからず、最初に質問した際の2種類のやり方で、片方が警告が出て、片方は出ないのがなぜなのか、未だによくわかりません。 しかし、とりあえず、前に進み、また必要があれば、振り返ってみたいと思います。 (警告は、対処療法ではなく、しっかりと理解して回避せよ、とあちこちに書いてはありますが、、、)
guest

回答1

0

「python 3.11.8,pandas 2.2.1」でしか確かめていませんが,「Copy-on-Write(CoW) モード」を有効にすると今回の警告(SettingWithCopyWarning)はなくなりました。有効にするには下記の 1行を追加ください。

pd.options.mode.copy_on_write = True

なお,この Copy-on-Write(CoW) モード は,pandas 3.0 からデフォルトになり,pandas 2.2 でも有効にすることが推奨されています。

Python

1import pandas as pd 2 3pd.options.mode.copy_on_write = True 4 5df = pd.DataFrame({'a': [0, 1, 2], 'b': [3, 4, 5], 6 'c': [6, 7, 8]}, index=['x', 'y', 'z']) 7print(df) 8# a b c 9# x 0 3 6 10# y 1 4 7 11# z 2 5 8 12print() 13df1 = df.iloc[:, [1]] 14 15print(df1) 16# b 17# x 3 18# y 4 19# z 5 20print() 21 22# rollingで移動平均を作る 23df1['SMA1'] = df1['b'].rolling(2).mean() 24 25print(df1) 26# b SMA1 27# x 3 NaN 28# y 4 3.5 29# z 5 4.5

投稿2024/03/17 05:37

編集2024/03/20 06:51
little_street

総合スコア535

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tamtam2020

2024/03/17 13:20

ありがとうございます。うまく行きました。そういう方法もあるんですね。勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.29%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問