pandas选择行范围

时间:2018-04-17 06:16:23

标签: python pandas conditional

我有一个简单的问题。我创建了一个具有许多特征的数据框。我想创建一个新列,选择两个特定行(将作为输入)之间的所有行。

假设数据帧如下:

data = {'currency': ['Euro', 'Euro', 'Euro', 'Dollar', 'Dollar', 'Yen', 'Yen', 'Yen', 'Pound', 'Pound', 'Pound, 'Pesos', 'Pesos'], 
    'cost': [34, 67, 32, 29, 48, 123, 23, 45, 78, 86, 23, 45, 67]}
df = pd.DataFrame(data, columns = ['currency', 'cost'])
df

df table

我想添加一个新列,在满足条件时分配1。在我的情况下,条件是两种特定货币之间的所有行。例如,假设我希望所有货币介于' Dollar'之间。和#Pound'。我的猜测是我必须创建一个面具并将其用作条件,这将说明选择第一个' Dollar'之间的所有行。排和最后一个' Pound'行(即第3-10行)。

我在创建该掩码时遇到问题,因为货币是按字母顺序选择的:

mask = (df['currency'] >= 'Dollar') & (df['currency'] <= 'Pound')

以上所有货币都会创建一个新列,除了&#39;日元&#39;。我可以看出为什么上面的失败,但却想不出一种做我想做的事情。

注意:相同的货币名称将成组,例如&#39;磅&#39;不能在4-5行,然后是8-10行。

提前致谢

2 个答案:

答案 0 :(得分:3)

通用解决方案也适用于重复索引:

a = df['currency'].eq('Dollar').cumsum()
b = df['currency'].eq('Pound').iloc[::-1].cumsum()
df['new'] = a.mul(b).clip_upper(1)

替代工作的唯一索引:

a = df['currency'].eq('Dollar').idxmax()
b = df['currency'].eq('Pound').iloc[::-1].idxmax()
df['new'] = 0
df.loc[a:b, 'new'] = 1

print (df)
   currency  cost  new
0      Euro    34    0
1      Euro    67    0
2      Euro    32    0
3    Dollar    29    1
4    Dollar    48    1
5       Yen   123    1
6       Yen    23    1
7       Yen    45    1
8     Pound    78    1
9     Pound    86    1
10    Pound    23    1
11    Pesos    45    0
12    Pesos    67    0

说明:

  1. Series.eq比较首先与==相同
  2. 获取cumsum
  3. 对于[::-1]
  4. 的第二个条件反向掩码
  5. mul多个一起,clip_upper
  6. 将非0替换为1

    第二个解决方案使用idxmax作为第一个索引值,并按1设置loc

答案 1 :(得分:2)

在逻辑或

上使用Numpy的积累
cumor = np.logical_or.accumulate

c = df.currency.values
d = c == 'Dollar'
p = c == 'Pound'

df.assign(new=(cumor(d) & cumor(p[::-1])[::-1]).astype(np.uint))

   currency  cost  new
0      Euro    34    0
1      Euro    67    0
2      Euro    32    0
3    Dollar    29    1
4    Dollar    48    1
5       Yen   123    1
6       Yen    23    1
7       Yen    45    1
8     Pound    78    1
9     Pound    86    1
10    Pound    23    1
11    Pesos    45    0
12    Pesos    67    0