Saya mendapatkan SettingWithCopyError, dan meskipun saya telah mengidentifikasi baris kode yang bermasalah, saya tidak dapat memahami mengapa kesalahan tersebut muncul.

Fungsi masalahnya adalah sebagai berikut:

def filter_log(df, search_string):
    results = df.loc[df['Message'].str.contains(search_string)]
    results.loc[:,'Duration'] = results.index.to_series().diff()
    results.loc[:,'Duration'] = results['Duration'].apply(lambda x: x.total_seconds())
    results = results.dropna(subset=['Duration'])

    results['Day'] = results.index.floor('d')
    results.loc[:,'Day'] = results['Day'].apply(lambda x: x.strftime('%Y-%m-%d'))

    return results

Fungsi mengambil kerangka data dan string pencarian seperti pada input, dan mengembalikan kerangka data yang difilter/dimanipulasi sebagai hasilnya.

Kesalahan terjadi pada baris 3 - results.loc[:,'Duration'] = results.index.to_series().diff()

Baris ini menghitung kenaikan waktu antara setiap baris kerangka data menggunakan metode .diff() pada indeks datetime dari kerangka data input.

Namun, saya tampaknya menggunakan pengindeksan .loc dengan benar, dan saya seharusnya tidak mengatur apa pun pada salinan. Menariknya, kesalahan hanya muncul saat pertama kali saya menjalankan skrip di lingkungan interaktif (atau setiap kali saya menjalankannya secara mandiri). Saat dijalankan setelah pertama kali dijalankan di lingkungan interaktif, kesalahan tidak terjadi.

Jejak tumpukan penuh adalah sebagai berikut:

Traceback (most recent call last):

  File "<ipython-input-1-d72a02ad5f86>", line 1, in <module>
    runfile('C:/00_Projects/99_Misc/aqis_log_analyser/aqis_log_analyser.py', wdir='C:/00_Projects/99_Misc/aqis_log_analyser')

  File "C:\apps\Anaconda2\lib\site-packages\spyder\utils\site\sitecustomize.py", line 710, in runfile
    execfile(filename, namespace)

  File "C:\apps\Anaconda2\lib\site-packages\spyder\utils\site\sitecustomize.py", line 86, in execfile
    exec(compile(scripttext, filename, 'exec'), glob, loc)

  File "C:/00_Projects/99_Misc/aqis_log_analyser/aqis_log_analyser.py", line 137, in <module>
    search_results = filter_log(log_df, search_string).loc[start:end]

  File "C:/00_Projects/99_Misc/aqis_log_analyser/aqis_log_analyser.py", line 94, in filter_log
    results.loc[:,'Duration'] = results.index.to_series().diff()

  File "C:\apps\Anaconda2\lib\site-packages\pandas\core\indexing.py", line 179, in __setitem__
    self._setitem_with_indexer(indexer, value)

  File "C:\apps\Anaconda2\lib\site-packages\pandas\core\indexing.py", line 337, in _setitem_with_indexer
    self.obj[key] = _infer_fill_value(value)

  File "C:\apps\Anaconda2\lib\site-packages\pandas\core\frame.py", line 2331, in __setitem__
    self._set_item(key, value)

  File "C:\apps\Anaconda2\lib\site-packages\pandas\core\frame.py", line 2404, in _set_item
    self._check_setitem_copy()

  File "C:\apps\Anaconda2\lib\site-packages\pandas\core\generic.py", line 1871, in _check_setitem_copy
    raise SettingWithCopyError(t)

SettingWithCopyError: 
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: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

Adakah saran tentang apa yang mungkin menyebabkan kesalahan dalam hal ini?

1
katamatsu 1 Mei 2018, 02:53

1 menjawab

Jawaban Terbaik

Akar penyebab SettingWithCopyError biasanya muncul beberapa baris sebelum baris yang disebutkan dalam traceback. Di sini, maksud Anda adalah menyalin subset df ke dalam DataFrame baru, memodifikasi DataFrame baru ini, dan mengembalikannya. Pandas tidak yakin apakah Anda bermaksud melakukan ini, atau apakah Anda bermaksud memodifikasi df yang asli.

Menambahkan .copy() eksplisit akan menghilangkan peringatan:

results = df.loc[df['Message'].str.contains(search_string)].copy()

Bacaan lebih lanjut: https://www.dataquest.io/blog/settingwithcopywarning/

2
Peter Leimbigler 1 Mei 2018, 05:38