2017-07-21 222 views
1

改造我修修补补一些丑陋的代码来解决这个问题,但希望找到一个Python的方式:熊猫横行的条件

df = pd.DataFrame({'signal':[1,0,0,1,0,0,0,0,1,0,0,1,0,0],'product':['A','A','A','A','A','A','A','B','B','B','B','B','B','B'],'price':[1,2,3,4,5,6,7,1,2,3,4,5,6,7],'price_B':[1,1,1,4,4,4,4,0,2,2,2,5,5,5,]}) 

我要创建“Price_B”列。对于每个“产品”子组,如果信号为1,则Price_B等于Price。如果信号为0,则Price_B等于前一行的价格。如果子组以“0”信号开始,则'price_B'将保持为0直到'信号”变成1

下面是我写的:

dfb = df.groupby('product').get_group('B') 
for i in dfb.index: 
    if dfb.loc[i, 'signal'] == 1: 
     dfb.loc[i, 'test'] = dfb.loc[i, 'price'] 
    else: 
     try: 
      dfb.loc[i, 'test'] = dfb.loc[i - 1, 'test'] 
     except KeyError: 
      dfb.loc[i, 'test'] = 0 

我知道这些代码是不合法的。有人可以帮忙吗?

+0

您在for循环中的代码没有正确缩进。 – IanS

+0

哦,是的。刚刚更新了for循环 –

+0

使用.loc()列表理解喜欢在我的回答下面 – 2Obe

回答

1

我会使用pd.Series.where以抵消数据,其中信号不1。然后向前填充并填充na。

def f(d): 
    dtype = d.price.dtype 
    p = d.price.where(d.signal.eq(1)) 
    return p.ffill().fillna(0).astype(dtype) 

df.assign(price_B=df.groupby('product', group_keys=False).apply(f)) 

    price price_B product signal 
0  1  1  A  1 
1  2  1  A  0 
2  3  1  A  0 
3  4  4  A  1 
4  5  4  A  0 
5  6  4  A  0 
6  7  4  A  0 
7  1  0  B  0 
8  2  2  B  1 
9  3  2  B  0 
10  4  2  B  0 
11  5  5  B  1 
12  6  5  B  0 
13  7  5  B  0 
+0

嗨,我想知道如何在f(d)函数中添加一个参数并将其应用于df? 现在f(d)只针对['price']列,但我想让它变为动态并让函数定位其他列,如['price2'] –

0
df["price_B"]=[df.loc[i-1,"price_B"] if df.loc[i,"signal"]==0 else df.loc[i,"price"] for i in range(len(df["price"]))] 

print(df) 

    price price_B product signal 
0  1  1  A  1 
1  2  1  A  0 
2  3  1  A  0 
3  4  4  A  1 
4  5  4  A  0 
5  6  4  A  0 
6  7  4  A  0 
7  1  4  B  0 
8  2  2  B  1 
9  3  2  B  0 
10  4  2  B  0 
11  5  5  B  1 
12  6  5  B  0 
13  7  5  B  0