python - 通过切片索引和条件行设置值

标签 python pandas dataframe multi-index

尝试通过在多索引上切片并考虑列“Z”条件值来设置列“X”值。我可以很容易地设置列“X”值,但我在尝试找出条件时遇到了困难。

import pandas as pd

FOOBAR = (['foo','foo','foo','foo','bar','bar','bar','bar'])
NUM1 = ([5,5,6,6,8,8,5,5])
NUM2 = ([1,1,2,2,3,3,1,1])
NUM3 = ([1001,1002,1002,1002,1003,1004,1004,1005])

#build and name index using data
index = pd.MultiIndex.from_arrays([FOOBAR,NUM1,NUM2,NUM3], 
                                  names=['iFOOBAR','iNUM1','iNUM2','iNUM3'])

df = pd.DataFrame({'X': [ 0, 1, 2, 3, 4, 5, 6, 7],
                   'Y': [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'],
                   'Z': [ 1, 2, 2, 4, 5, 6, 7, 7],
                   'FL': [0.1,0.1,0.2,0.2,0.4,0.4,0.1,0.1]
                   }, index=index)

df.sortlevel(inplace=True)
idx = pd.IndexSlice

#original df
#                            FL  X  Y  Z
#iFOOBAR iNUM1 iNUM2 iNUM3              
#bar     5     1     1004   0.1  6  G  7
#                    1005   0.1  7  H  7
#        8     3     1003   0.4  4  E  5
#                    1004   0.4  5  F  6
#foo     5     1     1001   0.1  0  A  1
#                    1002   0.1  1  B  2
#        6     2     1002   0.2  2  C  2
#                    1002   0.2  3  D  4

#set value in 'X' based on index
newdf = df.loc[idx['foo',5,1,:], idx['X']] = 999

#new df
#                            FL    X  Y  Z
#iFOOBAR iNUM1 iNUM2 iNUM3                
#bar     5     1     1004   0.1    6  G  7
#                    1005   0.1    7  H  7
#        8     3     1003   0.4    4  E  5
#                    1004   0.4    5  F  6
#foo     5     1     1001   0.1  999  A  1
#                    1002   0.1  999  B  2
#        6     2     1002   0.2    2  C  2
#                    1002   0.2    3  D  4

#set value in 'X' base on index and 'Z' == 2 ???
#nextdf = df.loc[idx['foo',5,1,:], idx['Z'== 2]], 'X' = 999

#next df: desired output
#                            FL    X  Y  Z
#iFOOBAR iNUM1 iNUM2 iNUM3                
#bar     5     1     1004   0.1    6  G  7
#                    1005   0.1    7  H  7
#        8     3     1003   0.4    4  E  5
#                    1004   0.4    5  F  6
#foo     5     1     1001   0.1    0  A  1
#                    1002   0.1  999  B  2
#        6     2     1002   0.2    2  C  2
#                    1002   0.2    3  D  4

最佳答案

这实际上有点棘手。感觉可能有更好的方法 - 但这里有一种方法取决于对索引内部结构的一点了解 - 构建满足您标准的位置集,然后将其全部传递给 iloc

In [80]: cond1 = df.index.get_locs(idx['foo',5, 1, :])

In [81]: cond2, = (df['Z'] == 2).nonzero()

In [82]: row_indexer = pd.Index(cond1).intersection(cond2)

In [83]: row_indexer
Out[83]: Int64Index([5], dtype='int64')

In [84]: col_indexer = df.columns.get_loc('X')

In [85]: df.iloc[row_indexer, col_indexer] = 999

In [90]: df
Out[90]: 
                            FL    X  Y  Z
iFOOBAR iNUM1 iNUM2 iNUM3                
bar     5     1     1004   0.1    6  G  7
                    1005   0.1    7  H  7
        8     3     1003   0.4    4  E  5
                    1004   0.4    5  F  6
foo     5     1     1001   0.1    0  A  1
                    1002   0.1  999  B  2
        6     2     1002   0.2    2  C  2
                    1002   0.2    3  D  4

关于python - 通过切片索引和条件行设置值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38879647/

相关文章:

python - 不适用于 Keras 框架的示例

regex - 如何使用 Pandas 拆分数据框?

python - 错误请求错误 : Nested transactions are not supported

python - 无法以编程方式验证用户身份

python - Docker 中的 Spacy Load 模型

python - 如何使用 strptime 将浮点/整数转换为日期?

python - 将 pandas 生成的图渲染到 matplotlib Canvas 以进行流式处理

python - 如何轻松处理 python 中的动态装饰器?

dataframe - 在 Julia DataFrame 的堆栈函数中将measure_vars 放在id_vars 之前的原因是什么?

r - 如何删除包含超过 2000 个 NA 值的所有列?