熊猫中的“复制”论点是否按预期工作?

时间:2019-06-13 20:15:17

标签: python pandas

我正在努力确保在运行代码时再也看不到SettingWithCopyWarning。在花了数小时阅读有关该主题的SO线程之后,我有更多问题,很少答案。让我感到沮丧的是,在各种情况下,copy参数似乎被完全忽略了。

例如:

>>> import numpy as np
>>> import pandas as pd

>>> pd.__version__
    '0.24.2'

>>> arr = np.random.randint(10, size=(5, 5))  
>>> df = pd.DataFrame(data=arr)  # default value for 'copy' argument is False
>>> df._is_view
    True

>>> df = pd.DataFrame(data=arr, copy=True)  # this should create a copy, but doesn't
>>> df._is_view
    True

>>> df = df.copy()  # this should create a copy, and does
>>> df._is_view
    False

>>> df.astype(dtype='float')  # default value for 'copy' argument is True
>>> df._is_view
    True
  1. 在这些示例中,我误解了copy争论的目的吗?
  2. _is_view属性(不可靠)吗?
  3. 在使用DataFrame构造函数和astype方法的情况下,建议使用哪些创建/保留副本状态的方法?

1 个答案:

答案 0 :(得分:2)

来自docs

  

copy:布尔值,默认为False从输入中复制数据。只影响   DataFrame / 2d ndarray输入

因此,此处的复制与您传递给DataFrame构造函数的输入有关。 继续您的示例:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

User

因此,当您传递db.Offers.aggregate([ { "$match": { "OfferId": { "$in": [ "DD3B57A3-5183-4FF8-9E3C-321F4298B58D", "C60E9CC5-7339-479E-8003-285F6BD195C7", "392951DD-5BCB-42F2-B1E9-C96180A0C01B", "1B6263C0-B8FD-4706-98DB-89D2ACE5C1BF", "0126406E-FF5B-448E-AFFB-6D253C4C720C" ] }, "Region": "ZA" } } ]) 时,它确实会创建输入数组的副本,并将其用作基础的numpy数组表示形式。

另一方面,

np.random.seed(0) arr = np.random.randint(10, size=(3, 3)) print(arr) [[5 0 3] [3 7 9] [3 5 2]] df1 = pd.DataFrame(arr, copy=False) df2 = pd.DataFrame(arr, copy=True) 与该DataFrame是否从另一个DataFrame复制有关。看看这些选择:

# Change the first cell of the numpy array to -999
arr[0, 0] = 999

print(df1)
     0  1  2
0  999  0  3
1    3  7  9
2    3  5  2

print(df2)
   0  1  2
0  5  0  3
1  3  7  9
2  3  5  2

现在,如果将它们分配给变量并进行更改,它们都会发出警告,但是在最简单的情况下,您对视图所做的更改将起作用,但是对副本的更改将保留在副本中。同样,

copy=True

将起作用。但是

_is_view

不会将“ a”更改为“ b”。因为replace方法是在切片的DataFrame的副本上调用的,所以它实际上是在更改副本并使原始# Start with a DataFrame which has mixed types df = pd.DataFrame({'A': [1, 2, 3], 'B': list('abc'), 'C': [1., 2., 3,]}) df['A']._is_view # single column selection returns a view Out: True df[['A', 'B']]._is_view # if you select multiple columns it becomes a copy Out: False df.loc[[0, 1], 'A']._is_view # if you select some rows it is a copy again Out: False df.loc[:, 'A']._is_view # same as selecting a single column Out: True 保持不变。但是正如cs95所评论的,df['A'].replace(1, 2, inplace=True) 是私有属性。这些可能会在将来发生变化,用户一般不应依赖这些实现细节。