我有一个数据框,其中包含500K行和7列,分别包含几天和开始日期和结束日期。
我在range(startDay,endDay)中搜索一个值(例如等于0)
例如,对于id_1,startDay = 1和endDay = 7,因此,我应该寻找D1到D7列的值。
对于id_2,startDay = 4,endDay = 7,因此,我应该从D4到D7列寻找值。 但是,我无法成功地找到其他列范围。
上述,
否则,我需要找到第一个零(考虑日期范围),例如对于id_3,在D2列(第2天)中找到第一个零。 id_3的starDay为1。我想看到2-1 = 1(D2-StartDay)
如果找不到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)
答案 0 :(得分:1)
您可以创建布尔数组来检查每一行中“ startDay”之上和“ endDay”之下且“ dx”列等于0的“ Dx”列。对于前两个条件,您可以使用{{ 3}},其中ufunc
是np.ufunc.outer
和np.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。