Pandas_切片赋值、SettingWithCopyWarning

筛选部分数据后,并把它们赋值到另外一筛选数据中,可能出现错位或者缺失值的情况。并报SettingWithCopyWarning
import pandas as pd
A = pd.DataFrame({'a': range(0, 10), 'b': range(1, 11)})
print('A = ')
print(A)

数据A 如下

A =
   a   b
0  0   1
1  1   2
2  2   3
3  3   4
4  4   5
5  5   6
6  6   7
7  7   8
8  8   9
9  9  10

我们可以看到数据A由两列组成:’a’列和’b’列,分别是0到9,1到10

B = A.loc[0::2, ]  # 提取奇数行
print('B = ')
print(B)

数据B如下:

B =
  a  b
0  0  1
2  2  3
4  4  5
6  6  7
8  8  9

注意:数据B是通过loc函数切片筛选奇数行,且它的 行索引并不连续

3.提取部分数据C

C = A.loc[1::2, ]  # 提取偶数列
print('C = ')
print(C)

数据C如下:

C =
  a   b
1  1   2
3  3   4
5  5   6
7  7   8
9  9  10

注意:数据C是通过loc函数切片筛选偶数行,且它的 行索引并不连续

4.将数据B中的’a’列赋值到数据C的’a’列

B['a'] = C['a']

pandas会弹出SettingWithCopyWarning警告

D:\Pyton\main.py:11: 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
  B['a'] = C['a']

那么B最终结果是什么呢

print('B = ')
print(B)
B =
    a  b
0 NaN  1
2 NaN  3
4 NaN  5
6 NaN  7
8 NaN  9

注意:数据C中’a’列并未赋值到数据B来,且原有的数据被修改为Nan

pandas无法判断切片后的是视图还是副本,即:切片后的数据,仅仅是一个视图,如果我们修改视图,不会修改原数据,但我们以上的代码对视图赋值时,pandas无法判断报出警告。(个人理解:我们赋值的时候仅仅是传入原数据C的 行索引,而非实际值,但这些索引又无法在数据B中找到,且传入的索引也没有数据B所需要的索引。故数据B中的’a’列为 NaN

如果 行索引一致,是否可以成功赋值

D = A.loc[1::2, ]  # 和数据C一致
D['a'] = C['b']  # 将数据C中'b'列赋值给D的'a'列
print('D = ')
print(D)

数据D结果如下:

D =
    a   b
1   2   2
3   4   4
5   6   6
7   8   8
9  10  10

虽然成功赋值,但是会有 警告

D:\Pyton\main.py:15: 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
  D['a'] = C['b']

该警告和前面一样一样的,说明这么赋值的方式 不对

如果接受数据中包含传入数据的行索引,也包含其他行索引,又是怎样的结果呢?

E = A.loc[1:, :]
E['a'] = C['b']
print('E = ')
print(E)

数据E如下:

E =
      a   b
1   2.0   2
2   NaN   3
3   4.0   4
4   NaN   5
5   6.0   6
6   NaN   7
7   8.0   8
8   NaN   9
9  10.0  10

注意:传入数据(如:数据C)和接受数据(如:数据E)的行数并不相等,但pandas 没有报错,同时也可以看到只有与数据C对应的行被赋值了,其他行被设置为 Nan,同时也会弹出 SettingWithCopyWarning警告

针对前面的分析,我们在处理类似问题时,需要利用.copy()对切片的数据进行备份,才能对数据进行赋值。如:

F = A.loc[1::2, ].copy()   # 比数据D多个.copy()
F['a'] = C['b']
print('F = ')
print(F)

结果如下:

F =
    a   b
1   2   2
3   4   4
5   6   6
7   8   8
9  10  10

补充,那如果我们将数据A整体当作筛选数据呢

G = A.loc[:, :]    # 仅比数据E多第一行
G['a'] = C['b']
print('G = ')
print(G)
print("A = \n", A)

其结果如下:

G =
      a   b
0   NaN   1
1   2.0   2
2   NaN   3
3   4.0   4
4   NaN   5
5   6.0   6
6   NaN   7
7   8.0   8
8   NaN   9
9  10.0  10
A =
       a   b
0   NaN   1
1   2.0   2
2   NaN   3
3   4.0   4
4   NaN   5
5   6.0   6
6   NaN   7
7   8.0   8
8   NaN   9
9  10.0  10

发现:数据G中仅有偶数行被修改,奇数行被设置为 Nan, 且 数据A也被修改,但是此过程中pandas 即没有报错,也没弹警告。

我们对数据进行切片时,而且后期还需要对这些数据进行修改,我们因该利用.copy()对切片后的数据进行备份。

                                                                            个人理解,勿喷,有错请指正

Original: https://blog.csdn.net/qq_39362837/article/details/127462987
Author: 棠木屋
Title: Pandas_切片赋值、SettingWithCopyWarning

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/677343/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球