如何修改通过 df.loc[row] 定义的系列中的数据框元素?
How can I modify a dataframe element from a Series defined through df.loc[row]?
我有代码,其中 function/method 接受系列(来自 df 的行)并且应该就地修改它,这样更改就会反映在原始 df 中。但是,我似乎无法 force 将修改作为视图而不是副本。来自 Stack Overflow documentation and a related question 的信息无法解决以下示例给出的问题:
import pandas as pd
pd.__version__ # 0.24.2
ROW_NAME = "r1"
COL_NAME = "B"
NEW_VAL = 100.0
# df I would like to modify in-place
df = pd.DataFrame({"A":[[1], [2], [3,4]], "B": [1.0, 2.0, 3.0]}, index=["r1", "r2", "r3"])
# a row (Series reference) is the input param to a function that should modify df in-place
record = df.loc[ROW_NAME]
record.loc[COL_NAME] = NEW_VAL
assert df.loc[ROW_NAME, COL_NAME] == NEW_VAL #False
以 record.loc
开头的行导致熟悉的警告:
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
,这可能是有道理的,除了 record
似乎引用 df
并且在某些情况下可以就地修改。这方面的一个例子:
record = df.loc[ROW_NAME]
record.loc["A"].append(NEW_VALUE)
assert NEW_VALUE in df.loc["r1", "A"] # True
我的问题是:如何从系列 record
中就地强制修改 df.loc[ROW_NAME, COL_NAME]
处的浮点值?澄清为什么可以在上面的示例中就地修改 A 列而不是 B 列的加分项。
其他相关问题:
- sub-indexing dataframes:copies vs views
- What rules does Pandas use to generate a view vs a copy?
我认为这种行为令人困惑,因为 record
在这种情况下是数据框行的浅表副本。
如果您引用 this stack post,听起来 .loc[]
通常应该是 return 副本而不是视图,如果 .loc
已链接。
我确实确认如果你直接修改原始数据框它会起作用。
df.loc[ROW_NAME, COL_NAME] = NEW_VAL
assert(df.loc[ROW_NAME, COL_NAME] == NEW_VAL) # True
至于 .append
仍然有效,这就是我提到 "shallow" 复制行为的原因。您的新记录副本仍包含对 A 列中原始列表的引用。请参阅 this post 以重温绑定到新对象与改变现有对象之间的区别。
根据问题中链接的来源和对文档的全面阅读,似乎无法强制返回视图与从 DataFrame 行生成的系列副本。
正如@Lilith Schneider 指出的那样,最初对此的困惑来自于 record = df.loc["r1"]
returns 浅拷贝 - 拷贝和视图的某种混合,可能会导致混淆并导致意外行为。
我有代码,其中 function/method 接受系列(来自 df 的行)并且应该就地修改它,这样更改就会反映在原始 df 中。但是,我似乎无法 force 将修改作为视图而不是副本。来自 Stack Overflow documentation and a related question 的信息无法解决以下示例给出的问题:
import pandas as pd
pd.__version__ # 0.24.2
ROW_NAME = "r1"
COL_NAME = "B"
NEW_VAL = 100.0
# df I would like to modify in-place
df = pd.DataFrame({"A":[[1], [2], [3,4]], "B": [1.0, 2.0, 3.0]}, index=["r1", "r2", "r3"])
# a row (Series reference) is the input param to a function that should modify df in-place
record = df.loc[ROW_NAME]
record.loc[COL_NAME] = NEW_VAL
assert df.loc[ROW_NAME, COL_NAME] == NEW_VAL #False
以 record.loc
开头的行导致熟悉的警告:
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
,这可能是有道理的,除了 record
似乎引用 df
并且在某些情况下可以就地修改。这方面的一个例子:
record = df.loc[ROW_NAME]
record.loc["A"].append(NEW_VALUE)
assert NEW_VALUE in df.loc["r1", "A"] # True
我的问题是:如何从系列 record
中就地强制修改 df.loc[ROW_NAME, COL_NAME]
处的浮点值?澄清为什么可以在上面的示例中就地修改 A 列而不是 B 列的加分项。
其他相关问题:
- sub-indexing dataframes:copies vs views
- What rules does Pandas use to generate a view vs a copy?
我认为这种行为令人困惑,因为 record
在这种情况下是数据框行的浅表副本。
如果您引用 this stack post,听起来 .loc[]
通常应该是 return 副本而不是视图,如果 .loc
已链接。
我确实确认如果你直接修改原始数据框它会起作用。
df.loc[ROW_NAME, COL_NAME] = NEW_VAL
assert(df.loc[ROW_NAME, COL_NAME] == NEW_VAL) # True
至于 .append
仍然有效,这就是我提到 "shallow" 复制行为的原因。您的新记录副本仍包含对 A 列中原始列表的引用。请参阅 this post 以重温绑定到新对象与改变现有对象之间的区别。
根据问题中链接的来源和对文档的全面阅读,似乎无法强制返回视图与从 DataFrame 行生成的系列副本。
正如@Lilith Schneider 指出的那样,最初对此的困惑来自于 record = df.loc["r1"]
returns 浅拷贝 - 拷贝和视图的某种混合,可能会导致混淆并导致意外行为。