为什么在分配数据帧转置时会丢失数据?

时间:2017-11-22 12:47:58

标签: python pandas dataframe transpose

假设我有一个类似

的数据框
df = pd.DataFrame({'A':[1,2,3,4],'B':[1,3,4,7]})
   A  B
0  1  1
1  2  3
2  3  4
3  4  7

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

df.T['C'] = 3

运行此数据后,数据框没有变化。

但问题是数据存储在哪里?为什么会出现任何错误?我期待这种作业的错误或像

这样的输出
   A  B
0  1  1
1  2  3
2  3  4
3  4  7
C  3  3

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

时,两者都没有发生

修改:正如@Zero提到的,我们可能需要做

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

3 个答案:

答案 0 :(得分:2)

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   

当您调用任何返回新DataFrame的方法时,会发生同样的事情。 df.drop(0)['C'] = 2df.reset_index()['C'] = 3df.drop_duplicates()['C'] = 3。原始DataFrame始终保持不变。还有另一个DataFrame是使用分配给它的确切行创建的,但是一旦执行该语句就会变得无法访问,因为您没有指向它的任何变量。对于CPython的垃圾收集,有一些有用的信息here

从@Bharath编辑:

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

T returns a copy。这意味着分配新内存来存储新对象。如果你查找python垃圾收集,你会发现内存中的每个对象都会保留一个指针指向它的指针。

当运行垃圾收集时,它会在内存中找到该对象,并看到它没有指针。因为它有零指针,垃圾收集将回收内存,对象永远消失。

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

之间的精确相似性
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返回一个全新对象的事实,这就变得很容易理解了(我已经说过了这一点,但是我试图把这一点推到家里) -

id(df.T)
4612098928

id(df.T)
4612098872

id(df.T)
4612098592

总之,您正在尝试修改您没有引用的对象,并且您没有看到对原始文件的任何更改,因为您没有进行任何更改。