将数据存储为单元格函数
我有一个 pandas 数据框(或者说是一个二维数组)。
假设我有一个变量 a
,而上面这个数据框中某个单元格的值(比如说位置在 (0,0) 的单元格)是 a
:
df = pandas.DataFrame()
df.at[0,0] = a
我应该怎么写代码,才能让如果 a
的值改变,位置在 (0,0) 的单元格也能自动改变呢?
我试过我上面写的代码,也试过用 lambda 函数。
1 个回答
你问的这个问题其实不太适合去做(大家在评论里也都提到了这一点)。原因是,如果你想用“简单”的类型来实现这个功能,你就需要用到指针(也就是存储实际值的内存地址),这会增加一些风险和复杂性,而普通的Python通常会把这些复杂的东西隐藏起来。当你用df.iloc[0,0]来访问某个元素时,pandas会返回给你一个实际值的副本,这正是大多数处理数据的人所期待的,而不是一个内存地址。暴露内存地址是很危险的,而且还需要额外的麻烦去解引用才能访问它的值。因此,没办法让两个变量指向同一个值。
如果你真的需要这种行为,可以使用一个可变的数据结构或对象来存储你的值,作为一种变通方法(正如@MichaelButscher所解释的)。一种简单的方法是用一个只包含一个值的列表,直接用mylist[0]来访问这个值。更复杂的方法是定义一个自定义类。如果你处理的是数字类型,下面的代码可以作为一个选项:
class referred_number:
def __init__(self, value=None):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, value):
self._value = value
def __add__(self, add_obj):
self._value = self._value + add_obj.value
return self
def __sub__(self, sub_obj):
self._value = self._value - sub_obj.value
return self
def __mult__(self, mult_obj):
self._value = self._value * mult_obj.value
return self
def __div__(self, div_obj):
self._value = self._value / div_obj.value
return self
def __str__(self):
return str(self._value)
这样做其实有点不够理想,因为你不仅失去了pandas在数字类型上强大的方法,还需要写很多特殊的方法来恢复一些基本的默认行为。下面的代码将按照你的想法工作,甚至可以进行一些算术运算。此外,我们实现的__str__方法会让任何打印这个变量或数据框时显示实际的值。
import pandas as pd
df = pd.DataFrame()
x = referred_number(1)
df.at[0,0] = x
df.at[0,1] = referred_number(5)
print(f"df:\n{df} \n\nx:{x}\n")
x.value = 5
print(f"df:\n{df} \n\nx:{x}\n")
df[0] = df[0] + referred_number(4)
print(f"df:\n{df} \n\nx:{x}\n")
df[0] = df[0] + referred_number(3)
print(f"df:\n{df} \n\nx:{x}\n")
df[0] = df[0] + referred_number(2)
print(f"df:\n{df} \n\nx:{x}\n")
df[0] = df[0] + referred_number(2)
print(f"df:\n{df} \n\nx:{x}\n")
# Expected but dangerous behaviour since x is added twice!!
df.at[0,2] = x
df[0] = df[0] + referred_number(4)
print(f"df:\n{df} \n\nx:{x}\n")
你只需要小心,不要用普通数字进行赋值或运算,而是使用用构造函数创建的数字,比如referred_number(2) + 2会报错。正如你可能注意到的,你想要的这个功能涉及更多的工作,失去了功能,并且容易出错,这就是为什么大家建议这样做是个坏主意。