如何在Pandas中修复SettingWithCopyWarning
当我们试图修改Pandas DataFrame中的数据时,可能会出现SettingWithCopyWarning。当我们写下一行有获取和设置操作的代码时,这个警告就会被抛出。
详细解释一下,使用get操作,Pandas不会保证get操作返回的结果是一个视图或副本。如果它返回的是一个视图,那么set操作会影响到原始的DataFrame。如果它返回的是副本,那么它将修改副本,但原始的DataFrame保持不变。所以这里我们不确定DataFrame是否发生了变化。
DataFrame
Student Name | Percentage | Grade |
---|---|---|
Akhil | – | – |
Sai | 65 | C |
Rohit | 90 | O |
Prasanth | 79 | B |
Divya | 89 | A |
抛出警告的代码
# import necessary packages
import pandas as pd
# create a dataframe
marks = pd.DataFrame({'Name': ['Akhil', 'Sai', 'Rohit', 'Prasanth', 'Divya'],
'Percentage': ['-', 65, 90, 79, 89],
'Grade': ['-', 'C', 'O', 'B', 'A']})
# Assign Absent if percentage is not specified
marks[marks.Percentage == '-'].Grade = 'Ab'
输出
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\generic.py:5303: 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
self[name] = value
解决方案
为了解决这个问题,在获取所需的数据时,不要进行切片,而是使用loc方法来获取所需的行和列。同时使用copy方法将DataFrame的副本存储在另一个变量中,这样我们就可以将获取和设置操作分成两行。
示例 1:
使用上面的DataFrame 和loc方法,同时在获得操作中获得所需的行和列。
# import necessary packages
import pandas as pd
# create a dataframe
marks = pd.DataFrame({'Name': ['Akhil', 'Sai', 'Rohit', 'Prasanth', 'Divya'],
'Percentage': ['-', 65, 90, 79, 89],
'Grade': ['-', 'C', 'O', 'B', 'A']})
# Assign Absent if percentage is not specified
marks.loc[marks.Percentage == '-', 'Grade'] = 'Ab'
# modified content
marks
输出
解释-代替了会产生警告的切片法,这里我们使用loc法。
注意 :但这种定位方法不能确保100%保证无警告的输出。所以建议创建一个原始数据框架的副本,并对其进行修改。
示例 2:
创建一个DataFrame的副本并通过使用loc和copy方法对其进行修改。
# import necessary packages
import pandas as pd
# create a dataframe
marks = pd.DataFrame({'Name': ['Akhil', 'Sai', 'Rohit', 'Prasanth', 'Divya'],
'Percentage': ['-', '-', 90, 79, 89],
'Grade': ['-', '-', 'O', 'B', 'A']})
# create a copy of original DataFrame whose
$ percentage is empty(absenties)
Absent_Students = marks.loc[marks.Percentage == '-', :].copy()
# Make their grade as 'Ab' which indicates absent.
Absent_Students.Grade = 'Ab'
# modified content
Absent_Students
输出
解释-上述Absent_Students是原始DataFrame的一个副本,只有缺席的学生。它确保我们只在DataFrame的副本上进行修改。所以它消除了视图和副本之间的混淆。