我的方案是函数应该能够修改pandas.DataFrame
内的值。但我不想将整个DataFrame暴露给函数,只需要修改需要修改的部分。这种透明性的一个原因是该函数将更加通用,能够指定从外部修改DataFrame的哪个部分。成像我可以编写一个函数mult(df_view, a)
,它将视图中的所有值乘以a
。请注意,我不想创建新的DataFrame。值更改应就地。
这是我的尝试:
df = pd.DataFrame([[1,1],[1,1]])
def mult(df_view, a):
df_view *= a
mult(df.loc[1,1], 2)
print(df)
这是(不受欢迎的)输出:
0 1
0 1 1
1 1 1
预期输出为:
0 1
0 1 1
1 1 2
请注意,如果我们直接进行分配(即没有该功能),它可以工作:
df = pd.DataFrame([[1,1],[1,1]])
df.loc[1,1] *= 2
print(df)
......给出:
0 1
0 1 1
1 1 2
所以,显然我在通过函数调用传递该视图时搞砸了一些东西。我已阅读此blog post from Jeff Knupp,我想我理解python的名称 - 对象绑定是如何工作的。我对DataFrames的理解是,当我调用df.loc[1,1]
时,它会生成一个代理对象,该对象指向具有[1,1]
窗口的原始DataFrame,以便进一步的操作(例如赋值)仅转到窗口内的元素。现在,当我通过函数调用传递df.loc[1,1]
时,该函数将名称df_view
绑定到代理对象。因此,在我的理论中,任何更改(即df_view *= a
)都应该应用于视图,从而应用于原始DataFrame中的元素。从结果来看,显然没有发生,似乎DataFrame在过程中被复制(我不知道在哪里),因为某些值在原始DataFrame之外被更改。
答案 0 :(得分:0)
请检查
>>> type(df.loc[1, 1])
numpy.int64
显然这不会起作用 - 你传入一个不可变的int,它没有绑定到外部DataFrame。
如果您使用简单的索引(可变构造)传递实际视图,它很可能工作。
>>> mult(df.loc[:, 1], 2)
>>> df
0 1
0 1 2
1 1 2
但是其他一些操作不起作用。
>>> mult(df.loc[:, :1], 2)
>>> df
0 1
0 1 2
1 1 2
总而言之,我认为这种控制流程是一个坏主意 - 更好的选择是在你展示作品时直接在索引上操作。当你在可能的情况下坚持不变性时,熊猫往往更友好(恕我直言)。
答案 1 :(得分:0)
在某些情况下,有时会difficult to detect出现数据副本的问题。
您可以通过索引函数来解决难题:
def mult(df,i,j,a):
df.loc[i,j]*=a
mult(df,1,1,2)
mult(df,1,slice(0,2),6)
print(df)
的
0 1
0 1 1
1 6 12