从python 3.8开始,Pandas不允许我在DataFrame中重新分配值

3duebb1j  于 2022-12-10  发布在  Python
关注(0)|答案(1)|浏览(161)

在Pandas 1.3.5和python 3.7或更早版本下运行的代码:

import pandas as pd
import numpy as np
hex_name = '123456abc'
multi_sub_dir_id_list = [hex_name, hex_name, hex_name]
multi_leaf_node_dirs = ['one', 'two', 'three'] 
x_dir_multi_index = pd.MultiIndex.from_arrays ([multi_sub_dir_id_list, multi_leaf_node_dirs], names = ['hex_name', 'leaf_name'])
leaf_name = 'one'
dirpath = '/a/string/path'
task_path_str = 'thepath'
multi_exec_df = pd.DataFrame (data = None, columns = x_dir_multi_index)
multi_exec_df.loc[task_path_str] = np.nan
multi_exec_df.loc[task_path_str][hex_name, leaf_name] = dirpath

从Python 3.8开始,一旦某个对象被赋值,所有未来的赋值都将被忽略。
是否不再允许使用此配方?
上面的内容之后应该是什么样子:

hex_name   leaf_name
123456abc  one        /a/string/path
           two        NaN
           three      NaN

以上内容之后的实际效果:

> multi_exec_df.loc[task_path_str]
hex_name   leaf_name
123456abc  one         NaN
           two         NaN
           three       NaN
Name: thepath, dtype: float64

我这次测试的目的

Python 3.10.8 (main, Oct 13 2022, 09:48:40) [Clang 14.0.0 (clang-1400.0.29.102)] on darwin
print(pd.__version__)
1.5.2
wpx232ag

wpx232ag1#

下面是我对代码功能的解释。
您的设置代码:

import pandas as pd
import numpy as np
hex_name = '123456abc'
multi_sub_dir_id_list = [hex_name, hex_name, hex_name]
multi_leaf_node_dirs = ['one', 'two', 'three'] 
x_dir_multi_index = pd.MultiIndex.from_arrays ([multi_sub_dir_id_list, multi_leaf_node_dirs], names = ['hex_name', 'leaf_name'])
leaf_name = 'one'
dirpath = '/a/string/path'
task_path_str = 'thepath'
multi_exec_df = pd.DataFrame (data = None, columns = x_dir_multi_index)
multi_exec_df.loc[task_path_str] = np.nan

此时,multi_exec_df是一个 Dataframe ,其中一行充满了nans:

hex_name  123456abc          
leaf_name       one two three
thepath         NaN NaN   NaN

并且multi_exec_df.loc[task_path_str]是包含来自第一行的数据的序列:

hex_name   leaf_name
123456abc  one         NaN
           two         NaN
           three       NaN
Name: thepath, dtype: float64

根据您的示例“执行上述操作后应该是什么样子”,我假设您正在尝试将值"/a/string/path"赋给列('123456abc', 'one')
我会这样做:

col = (hex_name, leaf_name)
multi_exec_df.loc[task_path_str, col] = dirpath

据我所知,使用loc或类似的方法是为 Dataframe 赋值的唯一方法。
现在我们来看看代码在做什么......
您执行的不是上面的代码,而是下面的代码行:

multi_exec_df.loc[task_path_str][hex_name, leaf_name] = dirpath

这相当于:

multi_exec_df.loc[task_path_str][(hex_name, leaf_name)] = dirpath

它的问题是multi_exec_df.loc[task_path_str]是 Dataframe 中的行的副本,而不是视图。

<ipython-input-26-2d4fae3863b0>:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  multi_exec_df.loc[task_path_str][hex_name, leaf_name] = dirpath

(也许你知道,但你没有提到它,所以我指出了它。不知道为什么你没有得到这个警告。如果你不熟悉什么是视图阅读文档在上面的链接在警告)。
您问“是否不再允许使用此配方?”
显然,这是允许的,但您必须接受将新值赋给行的副本,而不是原始 Dataframe 中的行。
我不知道这是否是一个副本,而不是一个观点改变了在某个时候,在Pandas的发展,如果这是你要问的。
这是用Pandas 1.5.1完成的。

相关问题