Python 在链接loc和iloc后更改熊猫中的值

Python 在链接loc和iloc后更改熊猫中的值,python,pandas,dataframe,Python,Pandas,Dataframe,我有以下问题:在df中,我想选择特定的行和特定的列,在这个选择中,取前n个元素并给它们分配一个新值。我天真地认为以下代码应该可以完成这项工作: 导入seaborn作为sns 作为pd进口熊猫 df=sns.load_数据集'tips' df.loc[df.day==太阳,吸烟者].iloc[:4]=是 loc和iloc都应将视图返回到df中,并且该值应被覆盖。但是,数据帧不会改变。为什么? 我知道如何解决这个问题——首先只使用loc创建一个新的df,然后使用iloc更改值并更新回原始df,如下所

我有以下问题:在df中,我想选择特定的行和特定的列,在这个选择中,取前n个元素并给它们分配一个新值。我天真地认为以下代码应该可以完成这项工作:

导入seaborn作为sns 作为pd进口熊猫 df=sns.load_数据集'tips' df.loc[df.day==太阳,吸烟者].iloc[:4]=是 loc和iloc都应将视图返回到df中,并且该值应被覆盖。但是,数据帧不会改变。为什么?

我知道如何解决这个问题——首先只使用loc创建一个新的df,然后使用iloc更改值并更新回原始df,如下所示

但是a我认为它不是最优的,b我想知道为什么顶级解决方案不起作用。为什么它返回的是视图的副本而不是视图

替代解决方案:

df=sns.load_数据集'tips' tmp=df.loc[df.day==太阳,吸烟者] tmp.iloc[:4]=是 df.loc[df.day==太阳,吸烟者]=tmp 注意:我读过,这真的很好,但他们没有解释这一点。他们关心的是df.loc[mask,z]和链接的df[z][mask]之间的差异。

我认为df.loc[].iloc[]是一个链接的赋值案例,pandas不能保证您最终会看到它。从:

是否为设置操作返回副本或引用,可能取决于上下文。这有时被称为链式分配,应该避免

由于loc中有一个过滤条件,pandas将创建一个新的pd.Series,然后将分配给它。例如,由于您将获得与df[smoker]相同的系列,因此以下内容将起作用:

但您将得到“设置为CopyWarning”警告

您需要重写代码,以便pandas将其作为单个loc实体处理

另一种可能的解决方法:

df.loc[df[df.day=="Sun"].index[:4], "smoker"] = 'Yes'

在您的情况下,可以定义要插补的列

让我们假设以下数据集

df = pd.DataFrame(data={'State':[1,2,3,4,5,6, 7, 8, 9, 10], 
                         'Sno Center': ["Guntur", "Nellore", "Visakhapatnam", "Biswanath", "Nellore", "Guwahati", "Nellore", "Numaligarh", "Sibsagar", "Munger-Jamalpu"], 
                         'Mar-21': [121, 118.8, 131.6, 123.7, 127.8, 125.9, 114.2, 114.2, 117.7, 117.7],
                         'Apr-21': [121.1, 118.3, 131.5, 124.5, 128.2, 128.2, 115.4, 115.1, 117.3, 118.3]})
df
    State   Sno Center      Mar-21  Apr-21
0   1       Guntur          121.0   121.1
1   2       Nellore         118.8   118.3
2   3       Visakhapatnam   131.6   131.5
3   4       Biswanath       123.7   124.5
4   5       Nellore         127.8   128.2
5   6       Guwahati        125.9   128.2
6   7       Nellore         114.2   115.4
7   8       Numaligarh      114.2   115.1
8   9       Sibsagar        117.7   117.3
9   10      Munger-Jamalpu  117.7   118.3
所以,我想把Sno中心等于Nellore的所有日期都改为0

结果

df
State   Sno Center      Mar-21  Apr-21
0   1   Guntur          121.0   121.1
1   2   Nellore         0.0     0.0
2   3   Visakhapatnam   131.6   131.5
3   4   Biswanath       123.7   124.5
4   5   Nellore         0.0     0.0
5   6   Guwahati        125.9   128.2
6   7   Nellore         0.0     0.0
7   8   Numaligarh      114.2   115.1
8   9   Sibsagar        117.7   117.3
9   10  Munger-Jamalpu  117.7   118.3
另一个选项是将列定义为列表

COLS = ["Mar-21", "Apr-21"]
df.loc[mask, COLS] = 0
使用iloc的其他选项


你试过:df.loc[df.day==Sun,smoker].iloc[:4]=[Yes]*4吗?是的,这不是问题所在。无论是添加长度正确的值列表,还是使用单个字符串,该列表都允许您为不同的行设置不同的值,字符串为所有行设置相同的值。您好,谢谢您的回答。然而,我几乎可以肯定,这在总体上是行不通的。使用df.index时,它使用整个数据帧,而不是loc所做的选择。因此,尽管在本例中,选择一个不好的并没有什么区别,但通常您需要索引顺序,而不是索引本身。同意。添加了另一个解决方案。是的,该解决方案有效。很好,我喜欢。如果有人能解释为什么会发生这样的事情,如果他们比你的更详细的话,我还是会等着接受你的答案。但是谢谢!补充了一些解释嗨,谢谢你的回答。然而,这并没有回答我的问题。A它解决了一个不同的问题,你没有选择Sno中心为Nellore的df中的前n个日期,B我仍然没有解释为什么我帖子中的链接分配返回一个副本而不是一个视图。这也不起作用,它将返回整个df。有一个修复方法,df.loc[mask.index[Mar-21,Apr-21]]=0 ie使用索引,但这只是@Alexander Volkovsky的一个更冗长的解决方案。
df
State   Sno Center      Mar-21  Apr-21
0   1   Guntur          121.0   121.1
1   2   Nellore         0.0     0.0
2   3   Visakhapatnam   131.6   131.5
3   4   Biswanath       123.7   124.5
4   5   Nellore         0.0     0.0
5   6   Guwahati        125.9   128.2
6   7   Nellore         0.0     0.0
7   8   Numaligarh      114.2   115.1
8   9   Sibsagar        117.7   117.3
9   10  Munger-Jamalpu  117.7   118.3
COLS = ["Mar-21", "Apr-21"]
df.loc[mask, COLS] = 0
COLS = df.iloc[:, 2:4].columns.tolist()
df.loc[mask, COLS] = 0
df.loc[mask, df.iloc[:, 2:4].columns.tolist()] = 0