我有一堆数据框,我试图对其进行切片并将其分配回原始名称。但我发现存在名称空间问题。以下是我所拥有的。
import pandas as pd
import numpy as np
df_a = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
df_b = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
mylist =[df_a, df_b]
def truncate_before(list_of_dfts, idx):
for dfts in list_of_dfts:
dfts = dfts[idx:]
print(dfts.head)
truncate_before(mylist, 11)
print(df_a)
在truncate_before函数内的print语句中,它显示3行,分别对应于第11、12和13行。但是最终的打印语句显示第0至13行。
因此,在函数之外,它会恢复为原始数据帧。我的印象是Python通过引用传递参数。我想念什么?
最佳答案
在truncate_before
中:
def truncate_before(list_of_dfts, idx):
for dfts in list_of_dfts:
dfts = dfts[idx:]
print(dfts.head)
for-loop
创建一个引用dfts
中的DataFrame的局部变量list_of_dfts
。但 dfts = dfts[idx:]
将新值重新分配给
dfts
。它不会更改list_of_dfts
中的DataFrame。有关变量名如何绑定到值以及相对于将新值绑定到变量名的操作如何更改值的详细说明,请参见Facts and myths about Python names and values。
这里有很多选择:
就地修改列表
def truncate_before(list_of_dfts, idx):
list_of_dfts[:] = [dfts[idx:] for dfts in list_of_dfts]
for dfts in list_of_dfts:
print(dfts.head)
因为分配给
list_of_dfts[:]
(调用list_of_dfts.__setitem__
)会就地更改list_of_dfts
的内容。import numpy as np
import pandas as pd
df_a = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
df_b = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
mylist = [df_a, df_b]
def truncate_before(list_of_dfts, idx):
list_of_dfts[:] = [dfts[idx:] for dfts in list_of_dfts]
print(mylist[0])
truncate_before(mylist, 11)
print(mylist[0])
说明
mylist[0]
已被截断。请注意,但是df_a
仍引用原始DataFrame。返回列表并将
mylist
或df_a, df_b
重新分配给结果使用返回值可能不需要就地修改
mylist
。要将全局变量
df_a
,df_b
重新分配给新值,您可以truncate_before
返回数据帧列表,然后重新分配df_a
和df_b
到返回值:
def truncate_before(list_of_dfts, idx):
return [dfts[idx:] for dfts in list_of_dfts]
mylist = truncate_before(mylist, 11) # or
# df_a, df_b = truncate_before(mylist, 11) # or
# mylist = df_a, df_b = truncate_before(mylist, 11)
但是请注意,同时通过
mylist
和df_a
和df_b
访问DataFrame可能不是很好,因为如上面的示例所示,这些值不会自动保持协调。使用mylist
应该足够了。将DataFrame方法与inplace参数一起使用,例如
df.drop
dfts.drop
(带有inplace=True
)修改dfts
本身:import numpy as np
import pandas as pd
df_a = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
df_b = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
mylist = [df_a, df_b]
def truncate_before(list_of_dfts, idx):
for dfts in list_of_dfts:
dfts.drop(dfts.index[:idx], inplace=True)
truncate_before(mylist, 11)
print(mylist[0])
print(df_a)
通过就地修改
dfts
,mylist
和df_a
和df_b
中的值在同一时间得到改变。
请注意,
dfts.drop
根据索引标签值删除行。所以以上依靠(假定)
dfts.index
是唯一的。如果dfts.index
不是唯一的,dfts.drop
的行可能多于idx
的行。例如,df = pd.DataFrame([1,2], index=['A', 'A'])
df.drop(['A'], inplace=True)
删除两行,使
df
为空的DataFrame。还请注意熊猫的核心开发人员有关使用
inplace
的警告:我个人的看法:我从不使用就地操作。语法更难
阅读,它没有任何优势。
这可能是因为
dfts.drop
在后台创建了一个新的数据框,然后调用
_update_inplace
私有方法将新数据分配给旧的DataFrame:
def _update_inplace(self, result, verify_is_copy=True):
"""
replace self internals with result.
...
"""
self._reset_cache()
self._clear_item_cache()
self._data = getattr(result,'_data',result)
self._maybe_update_cacher(verify_is_copy=verify_is_copy)
由于无论如何都必须创建临时
result
,因此与简单的重新分配相比,“就地”操作没有内存或性能上的好处。关于python - 以编程方式将Pandas数据框切片,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35102908/