DataFrame多列的条件更新

时间:2018-01-21 13:18:54

标签: python pandas numpy dataframe

我正在为以下问题寻找更优雅和Pythonic的代码:

开始列中,每个项目都有一个发布周(从1到4),我添加了 W1,...,W4 列。

接下来我想以这种方式更新列(基本上,用零替换发布周和前一周和后一周的列):

   start  W1  W2  W3  W4
      1   0   0   1   1
      2   0   0   0   1
      3   1   0   0   0
      4   1   1   0   0

我现在就这样做:

import pandas as pd

data = {'start': [1,2,3,4]}
df = pd.DataFrame(data)
for i in range(1,4+1):
    df['W'+str(i)] = 1

for index, i in enumerate(df['start']):
    if i==1:
        df.ix[index, 'W1'] = 0
        df.ix[index, 'W2'] = 0
    elif i==4:
        df.ix[index, 'W3'] = 0
        df.ix[index, 'W4'] = 0
    else:
        df.ix[index, 'W'+str(i-1)] = 0
        df.ix[index, 'W'+str(i)] = 0
        df.ix[index, 'W'+str(i+1)] = 0

2 个答案:

答案 0 :(得分:1)

执行广播numpy比较以获取掩码,并将相应索引处的值设置为0

df.set_index('start', inplace=True)

i = df.index.values
j = np.arange(1, len(df) + 1)[:, None]

df.values[(i - 1 <= j) & (j <= i + 1)] = 0
df

       W1  W2  W3  W4
start                
1       0   0   1   1
2       0   0   0   1
3       1   0   0   0
4       1   1   0   0

<强>详情

i
array([1, 2, 3, 4]) 

j 
array([[1],
       [2],
       [3],
       [4]])

首先,计算面具 -

m = (i - 1 <= j) & (j <= i + 1)
m

array([[ True,  True, False, False],
       [ True,  True,  True, False],
       [False,  True,  True,  True],
       [False, False,  True,  True]], dtype=bool)

掩码m适用于整个数据帧。只需在values上编制索引,然后将单元格设置为0 -

df.values[m] = 0

要重置索引,请使用reset_index -

df.reset_index()

   start  W1  W2  W3  W4
0      1   0   0   1   1
1      2   0   0   0   1
2      3   1   0   0   0
3      4   1   1   0   0

答案 1 :(得分:1)

从你的df

df = df.astype(int)

start   W1  W2  W3  W4
0   1   1   1   1   1
1   2   1   1   1   1
2   3   1   1   1   1
3   4   1   1   1   1

您可以使用以下函数将map应用于df以重新计算值:

def func(pivot):
    return [1 if abs(col-pivot) > 1 else 0 for col in [1,2,3,4]]

这是我的第一个地图选项,不必要的复杂:

df['W1'], df['W2'], df['W3'], df['W4'] = zip(*df['start'].map(func))

这个来自@QuantChristo,好多了

weeks = ['W1','W2','W3','W4']
df[weeks] = df['start'].map(func)

在这两种情况下你都得到df:

start   W1  W2  W3  W4
0   1   0   0   1   1
1   2   0   0   0   1
2   3   1   0   0   0
3   4   1   1   0   0