两个数据框的列表,如果我更改列表元素(数据框),数据框是否会更改

时间:2019-08-07 17:55:16

标签: python dataframe

我正在研究kaggle的泰坦尼克号问题。在数据预处理步骤中,我想结合训练和测试数据帧。所以,我做了一个这样的变量组合。

combine = [df_train, df_test]

我看到了异常的行为,如果我更改Combine变量中的元素,则训练和测试数据帧会自动更新。

for dataset in combine:
    dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+)\.', expand=False)
    print(dataset["Title"].unique())

for dataset in combine:
    dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt', 'Col',\
    'Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')

    dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
    dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
    dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')

这样做之后,我检查了df_train,它具有“标题”列。

然后,我尝试了这个。 如果我通过这样做将列从df_train中删除

df_train = df_train.drop(["Ticket", "Cabin"], axis=1)
df_test = df_test.drop(["Ticket", "Cabin"], axis = 1)

直接从数据框中删除这两列之后,合并变量本身不会更新。

我想了解当我更改Combine变量中的元素时df_train如何更新。但是,如果我如上所述通过删除列直接更改df_train和df_test,则Combine变量不会更改。

2 个答案:

答案 0 :(得分:0)

在Python中,列表是可变的,每个对象都引用内存中的某些空间。

在这种情况下,您的联合收割机所指向的内存与df_train和df_test相同。好吧,实际上,您的联合收割机在内存中拥有自己的唯一空间,但是它的索引0和索引1的内存与df_train和df_test的内存空间相同。

这是一个例子:

arr_1 = [1, 3, 5]
arr_2 = [3, 6, 7]
arr_3 = [arr_1, arr_2]
print(id(arr_3), id(arr_1))

在这里,两个阵列的存储位置都不同,这很有意义。 arr_3在内存中占据唯一的空间。但是,

print(id(arr_3[0]), id(arr_1))

表明arr_3的第一个索引与arr_1具有完全相同的内存地址,这意味着它们都指向相同的数据。

因此,如果您更改arr_3 [0]或arr_1中的任何内容,那么您将更改同一数据。这是可变性的本质。

现在,在您所处的情况下,放下一列时,它不会影响合并对象,因为放下的位置不正确。您正在将df_train重新分配给新的数据帧,这实际上是内存中的新空间。

为避免这种情况,您可以导入副本库,并使用copy.deepcopy来执行两个数据集的深层副本。深拷贝将为对象分配唯一的内存空间。

答案 1 :(得分:0)

这是一个简化的示例:

>>> info = [1,2]
>>> other = {'hello': 'world'}
>>> combined = [info, other]
>>> combined[0].append(567)
>>> combined, info
([[1, 2, 567], {'hello': 'world'}], [1, 2, 567])
>>> combined[1]['one'] = 1
>>> combined, info
([[1, 2, 567], {'hello': 'world', 'one': 1}], [1, 2, 567])
>>> combined, other
([[1, 2, 567], {'hello': 'world', 'one': 1}], {'hello': 'world', 'one': 1})
>>> info = [0]
>>> combined, info
([[1, 2, 567], {'hello': 'world', 'one': 1}], [0])

诸如append__setitem__(也称为thing['key'] = stuff)之类的方法原位修改原始对象。将对象放入列表中并不一定要复制它,在这种情况下,它是将指向这些对象的指针放入列表中,因此,例如combined[0].append(567)实际上修改了称为info 通过存储在combined 中的指针。

请注意,现在同一对象(!)具有两个引用:名称info和对象combined。将名称info重新绑定到info = [0]中的不同对象应该会删除旧对象,对吗?好吧,是的,但前提是上述名称是对该对象的唯一引用。在我们的案例中,如前所述,有两个 ,因此第二个引用有效,对象本身也有效。现在info绑定到一个完全不同的对象,并且不影响旧对象,仍然可以使用combined[0]对其进行访问。