每行选择不同的列

时间:2019-04-30 17:30:02

标签: python-3.x pandas numpy

我有一个数据框,其中包含500K行和7列,分别包含几天和开始日期和结束日期。

我在range(startDay,endDay)中搜索一个值(例如等于0)

例如,对于id_1,startDay = 1和endDay = 7,因此,我应该寻找D1到D7列的值。

对于id_2,startDay = 4,endDay = 7,因此,我应该从D4到D7列寻找值。 但是,我无法成功地找到其他列范围。

上述,

  1. 如果startDay> endDay,我应该看到“ -999”
  2. 否则,我需要找到第一个零(考虑日期范围),例如对于id_3,在D2列(第2天)中找到第一个零。 id_3的starDay为1。我想看到2-1 = 1(D2-StartDay)

  3. 如果找不到0,我想看到“ 8”

这是我的数据;

data = {
        'D1':[0,1,1,0,1,1,0,0,0,1],
        'D2':[2,0,0,1,2,2,1,2,0,4],
        'D3':[0,0,1,0,1,1,1,0,1,0],
        'D4':[3,3,3,1,3,2,3,0,3,3],
        'D5':[0,0,3,3,4,0,4,2,3,1],
        'D6':[2,1,1,0,3,2,1,2,2,1],
        'D7':[2,3,0,0,3,1,3,2,1,3],
        'startDay':[1,4,1,1,3,3,2,2,5,2],
        'endDay':[7,7,6,7,7,7,2,1,7,6]
        }
data_idx = ['id_1','id_2','id_3','id_4','id_5',
            'id_6','id_7','id_8','id_9','id_10']
df = pd.DataFrame(data, index=data_idx)

我想看的东西

df_need = pd.DataFrame([0,1,1,0,8,2,8,-999,8,1], index=data_idx)

1 个答案:

答案 0 :(得分:1)

您可以创建布尔数组来检查每一行中“ startDay”之上和“ endDay”之下且“ dx”列等于0的“ Dx”列。对于前两个条件,您可以使用{{ 3}},其中ufuncnp.ufunc.outernp.less_equal,例如: 将numpy导入为np

arr_bool = ( np.less_equal.outer(df.startDay, range(1,8)) # which columns Dx is above startDay
            & np.greater_equal.outer(df.endDay, range(1,8)) # which columns Dx is under endDay
            & (df.filter(regex='D[0-9]').values == 0)) #which value of the columns Dx are 0

然后,您可以使用np.greater_equal查找每行的第一个True。通过加1并删除'startDay',您将获得所需的值。然后,您需要使用np.argmax查找其他条件,以在df.startDay >= df.endDay的行中用True将值替换为-999(如果没有{{1})则将值替换为8,例如:

arr_bool

一个注释:为了得到df_need = pd.DataFrame( (np.argmax(arr_bool , axis=1) + 1 - df.startDay).values, index=data_idx, columns=['need']) df_need.need= np.select( condlist = [df.startDay >= df.endDay, ~arr_bool.any(axis=1)], choicelist = [ -999, 8], default = df_need.need) print (df_need) need id_1 0 id_2 1 id_3 1 id_4 0 id_5 8 id_6 2 id_7 -999 id_8 -999 id_9 8 id_10 1 的-999,我在条件id_7中使用了条件df.startDay >= df.endDay,而不是像您的问题那样使用np.select,但是您可以严格要求比较,在这种情况下,您得到8而不是-999。