Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用布尔掩码对数据帧的分层列进行赋值?_Python_Pandas_Boolean Expression_Hierarchical - Fatal编程技术网

Python 如何使用布尔掩码对数据帧的分层列进行赋值?

Python 如何使用布尔掩码对数据帧的分层列进行赋值?,python,pandas,boolean-expression,hierarchical,Python,Pandas,Boolean Expression,Hierarchical,我有这样一个数据帧: import pandas as pd df = pd.DataFrame({ "time": [1, 2, 1, 2], "site": ['a', 'a', 'b', 'b'], "val1": [11, 12, 21, 22], "val2": [101, 102, 201, 202] }) df.set_index(['time', 'site'], inplace=True, append=False) df = df.unst

我有这样一个数据帧:

import pandas as pd
df = pd.DataFrame({
    "time": [1, 2, 1, 2], 
    "site": ['a', 'a', 'b', 'b'], 
    "val1": [11, 12, 21, 22],
    "val2": [101, 102, 201, 202]
})
df.set_index(['time', 'site'], inplace=True, append=False)
df = df.unstack("site")
print df

     val1     val2     
site    a   b    a    b
time                   
1      11  21  101  201
2      12  22  102  202
ix = (df.val1 > 20) | (df.val2 < 102)
df.val1[ix] = 50
df.val2[ix] = 150
我想更改一些与布尔过滤器匹配的值。e、 g:

ix = df.val1 > 20
print ix

site      a     b
time             
1     False  True
2     False  True
尝试的自然方法是
df.val1[ix]=50
。这会执行预期的赋值,但会给出一个警告:
SettingWithCopyWarning:试图在数据帧的切片副本上设置值。尝试改用.loc[row\u indexer,col\u indexer]=value

因此,现在我正在尝试使用
df.loc
实现类似的功能。但是我找不到任何方法将
df.loc
与这种布尔掩码一起使用。这似乎是因为我使用的是分层列,也就是说,如果我只有一组值(val1),我不会有太多问题。不幸的是,在层次结构列上使用布尔过滤器的赋值在本文中没有很好地介绍

我试图引用
df.loc[:,'val1',ix]
,但这会导致
索引错误:索引器太多。我已经尝试了
df.loc[:,'val1'][ix]=50
,这是可行的,但给出了带有copywarning的
设置

我可以使用
df.val1=df.val1.where(~ix,other=50)
,但这似乎不直观、低效且不灵活(例如,无法轻松扩展以在现有值上添加10)

是否有其他基于布尔掩码的索引方法可用于为数据帧的层次列赋值

编辑以扩展问题:

我没有意识到这会是一个问题,但我实际上希望根据
val1
val2
列中的值进行过滤,并更改这两组列中的值,如下所示:

import pandas as pd
df = pd.DataFrame({
    "time": [1, 2, 1, 2], 
    "site": ['a', 'a', 'b', 'b'], 
    "val1": [11, 12, 21, 22],
    "val2": [101, 102, 201, 202]
})
df.set_index(['time', 'site'], inplace=True, append=False)
df = df.unstack("site")
print df

     val1     val2     
site    a   b    a    b
time                   
1      11  21  101  201
2      12  22  102  202
ix = (df.val1 > 20) | (df.val2 < 102)
df.val1[ix] = 50
df.val2[ix] = 150
ix=(df.val1>20)|(df.val2<102)
df.val1[ix]=50
df.val2[ix]=150

有没有一种简单的索引方法可以做到这一点?使用numpy ndarray非常简单,但使用pandas数据帧似乎要复杂得多。

您可以使用列表来选择列

idx = df[['val1']] > 20

idx
Out[39]: 
       val1      
site      a     b
time             
1     False  True
2     False  True

df[idx] = 50

df
Out[41]: 
     val1     val2     
site    a   b    a    b
time                   
1      11  50  101  201
2      12  50  102  202

当您首先按列名从数据帧中选择序列,然后尝试使用布尔掩码并为其赋值时,就会出现此问题。具体来说,带有布尔掩码的赋值在内部转换为提取的_数据。其中(-mask,other=value,inplace=True),这将引发设置WithCopyWarning

如果pandas能够保证这种操作会改变原始数据帧,而不是发出警告,那就太好了。(顺便说一下,如果链式操作的顺序颠倒,
df[ix][“val1”]=500
df[ix][[“val1”,“val2”]=500
不会发出警告,但无法更新原始数据帧)。在解决这一问题之前,有两个变通办法

(1) 受@cncggvg答案的启发:构造一个指定所有需要更新的元素的索引,而不是将两个索引操作链接在一起

# create a partial index for the boolean operation
# note: this specifies the second-level columns it will act on, but not 
# the first level, since that was given unambiguously in the df[col] expression
ix = (df["val1"] > 20) | (df["val2"] < 102)
# build an index that specifies both the first and second-level columns
ix2 = pd.concat({"val1": ix}, axis=1)
# or, to do the same assignment on multiple first-level columns:
ix2 = pd.concat({"val1": ix, "val2": ix}, axis=1)
# do the assignment in one step, with no chaining
df[ix2] = 50
# or derive new values from current values
df[ix2] = df[ix2]+50

这两者都比我想要的更麻烦,所以我可以将数据帧的相关部分复制到numpy阵列中,然后从那里开始处理它们。根据

的说法,这应该会有更好的性能。您是否可以选择将列展平?谢谢,这是对我所问问题的一个很好的回答。不幸的是,我忘了提到我还想更改val2列中的相应条目,类似于
ix=(df.val1>20)|(df.val2>200);df.val1[ix]=50;df.val2[ix]=150
。你知道怎么做吗?用标准的numpy Ndaray很简单,但在熊猫身上似乎更棘手。