当分配给数据框的转置时,为什么我们会丢失数据



我有一个像

这样的数据框
df = pd.DataFrame({'A':[1,2,3,4],'B':[1,3,4,7]})
   b0 1 11 2 32 3 43 4 7

当我将一些数据分配给数据框的转置时,没有错误,即

df.T['C'] = 3

运行此功能后的数据框没有更改。

但问题是数据存储在哪里?为什么不给任何错误?我期望这种分配的错误或

之类的输出
   b0 1 11 2 32 3 43 4 7C 3 3

当我做df.T['C'] = 3

时都没有发生

edit :@zero提及,我们可能必须做

df = df.T.assign(C=3).T # Which is like df.loc['C',:] = 3

df.T是一个不同的对象。您所做的更改不会反映在原始DF中。它在哪里?由于没有指向它的变量,要么已经由垃圾收集器收集,要么正在等待收集。您无法访问它。

您可以做的是创建一个新的变量

transposed = df.T
transposed['C'] = 3
transposed
Out: 
   0  1  2  3  C
A  1  2  3  4  3
B  1  3  4  7  3   

当您调用任何返回新数据框的方法时,也会发生同样的事情。df.drop(0)['C'] = 2df.reset_index()['C'] = 3df.drop_duplicates()['C'] = 3。原始的数据帧始终保持不变。在执行该语句的情况下,由于没有任何指向它的变量,因此创建了另一个数据框,但在执行该语句时就无法访问它。对于Cpython的垃圾收集,这里有一些有用的信息。


@bharath的编辑:

(我的一位老师给出的解释)

T returns a copy。这意味着将新的内存分配以存储新对象。如果您查找Python垃圾收集,您会发现内存中的每个对象都可以反对指向它的指针。

运行垃圾收集时,它将在内存中找到此对象,并看到其指针为零。因为它的指针为零,所以垃圾收集将收回内存,并且对象永远消失。

因此,建议通过分配给名称(或变量)来保持单个指针指向对象。

方法 T do return super(DataFrame, self).transpose(1, 0, **kwargs)
它将创建另一个数据框。

添加到现有答案中,我想提请您注意 -

之间的巧妙相似性
df
   A  B
0  1  1
1  2  3
2  3  4
3  4  7
df.T['C'] = 3
df
   A  B
0  1  1
1  2  3
2  3  4
3  4  7

,与Python list S-

类似的情况
l = [1, 2, 3, 4, 5]
l[:].append(6)
l
[1, 2, 3, 4, 5]

在两种情况下都会发生的是创建新对象!然后将操作应用于新创建的对象,随后,该对象是收集的垃圾,因为没有主动引用指向它。您可以看到这一点 -

import sys
sys.getrefcount(df.T)
1

只有一个对该对象的引用(在那个时间点的引用,随后丢失了)。一旦您接受df.T返回A 全新对象的事实,这将变得容易理解(我已经说过了,但是我正在尝试将重点带回家) -

id(df.T)
4612098928
id(df.T)
4612098872
id(df.T)
4612098592

总而言之,您正在尝试修改您没有参考的新鲜对象,并且您没有看到对原件的任何更改,因为您没有进行任何参考。

<</p>

最新更新