我有一个像这样的DataFrame:
NoDemande NoUsager Sens IdVehiculeUtilise Fait HeurePrevue HeureDebutTrajet
0 42191000823 001208 + 246Véh 1 08:20:04 08:22:26
1 42191000822 001208 + 246Véh 1 08:20:04 08:18:56
2 42191000822 001208 - 246Véh -99 09:05:03 08:56:26
3 42191000823 001208 - 246Véh 1 09:05:03 08:56:26
4 42191000834 001208 + 246Véh 1 16:50:04 16:39:26
5 42191000834 001208 - 246Véh 1 17:45:03 17:25:10
6 42192000761 001208 + 246Véh -1 08:20:04 08:15:07
7 42192000762 001208 + 246Véh 1 08:20:04 08:18:27
8 42192000762 001208 - 246Véh -99 09:05:03 08:58:29
9 42192000761 001208 - 246Véh -11 09:05:03 08:58:29
我从df[df.duplicated(['NoUsager','NoDemande'],keep=False)]
获取此数据框,以确保我的行成对。当NoDemande
是连续数字(如42191000822和42191000823,42192000761和42192000762)并且列HeurePrevue
相同时,我想删除一对行,这意味着记录被记录两次。我必须删除一对,我想在列Fait
中预先设置一个具有更多正数的那个(至少一个大于0)
所以我的结果应该是这样的:
NoDemande NoUsager Sens IdVehiculeUtilise Fait HeurePrevue HeureDebutTrajet
0 42191000823 001208 + 246Véh 1 08:20:04 08:22:26
3 42191000823 001208 - 246Véh 1 09:05:03 08:56:26
4 42191000834 001208 + 246Véh 1 16:50:04 16:39:26
5 42191000834 001208 - 246Véh 1 17:45:03 17:25:10
7 42192000762 001208 + 246Véh 1 08:20:04 08:18:27
8 42192000762 001208 - 246Véh -99 09:05:03 08:58:29
我知道这是关于OR
逻辑的,但我不知道如何实现它。
任何帮助将不胜感激〜
答案 0 :(得分:1)
我对这个问题的处理方法是制作两个包含检查条件的列(相同的heure和连续增加的NoDemande)。然后迭代数据帧,根据Fait列删除不需要的对。
这有点像hacky代码,但这似乎可以解决问题:
# Recreate DataFrame
df = pd.DataFrame({
'NoDemande': [23, 22, 22, 23, 34, 34, 61, 62, 62, 61],
'HeurePrevue': [84, 84, 93, 93, 64, 73, 84, 84, 93, 93],
'Fait': [1, 1, -99, 1, 1, 1, -1, 1, -99, -11]
}, columns=['NoDemande', 'Fait', 'HeurePrevue'])
# Make columns which contain conditions for inspection
df['sameHeure'] = df.HeurePrevue.iloc[1:] == df.HeurePrevue.iloc[:-1]
df['cont'] = df.NoDemande.diff()
# Cycle over rows
for prev_row, row in zip(df.iloc[:-1].itertuples(), df.iloc[1:].itertuples()):
if row.sameHeure and (row.cont == 1): # If rows are continuous and have the same Heure delete a pair
pair_1 = df.loc[df.NoDemande == row.NoDemande]
pair_2 = df.loc[df.NoDemande == prev_row.NoDemande]
if sum(pair_1.Fait > 0) < sum(pair_2.Fait > 0): # Find which pair to delete
df.drop(pair_1.index, inplace=True)
else:
df.drop(pair_2.index, inplace=True)
df.drop(['cont', 'sameHeure'], 1, inplace=True) # Throw away the added columns
结果:
print(df)
NoDemande Fait HeurePrevue
0 23 1 84
3 23 1 93
4 34 1 64
5 34 1 73
7 62 1 84
8 62 -99 93
答案 1 :(得分:0)
我在这里看到两个解决方案。 第一个是基于这样的建议:您的数据集中始终有连续的条目对 - 如果任何条目有一对,则此对出现在此条目之后。然后你应该使用步长= 2循环数据帧:
for i in range(0,x,2):
your action
在此循环中,您可以比较两个条目并删除具有负值的条目。
我的第二个主张有点复杂。
首先,您应该复制和延迟(按特定行数移动)所有列。这可以通过以下函数完成(仅适用于NoDemande,为每个列使用循环执行此操作):
df.NoDemande = df.NoDemande.shift(-1)
看起来像:
NoDemande NoDemande_lagged
0 42191000823 42191000822
1 42191000822 42191000822
2 42191000822 42191000823
3 42191000823 42191000834
然后比较NoDemande和NoDemande_lagged列中同一行中的两个值。如果42191000822中的数字大于或小于NoDemande中的值,则比较 Fait 和 Fait_lagged 并选择更正值,您应该将其粘贴到新值中列 Fait_selected 。您应该对其他列执行相同操作,以便每列都具有滞后副本和选定副本。之后你应该删除你的下一行,因为你已经将它与前一行进行了比较。 最后,您应该删除原始和滞后的列,只留下&#34; _selected&#34;。
对不起复杂的解释,希望,无论如何这对你有所帮助。如果您熟悉RapidMiner,我可以解释如何在那里做到这一点,它会更容易。我为各种概念提供了一些想法,可以帮助您解决问题。
答案 2 :(得分:0)
这是一个冗长的解决方案,可能会有较短的解决方案。 frame0
是您在上面发布的确切框架。
首先获取数据,按NoDemande
对其进行排序,拆分并重新组合,以便在同一行中有两个配对。让事情变得更容易:
frame0.HeurePrevue = pd.to_datetime(frame0.HeurePrevue)
frame0 = frame0.sort_values('NoDemande').reset_index(drop=True)
frameA = frame0.iloc[::2].reset_index(drop=True)
frameB = frame0.iloc[1::2].reset_index(drop=True)
frame1 = pd.concat([frameA,frameB],axis=1,join='inner')
frame1.columns = [u'NoDemande1', u'NoUsager1', u'Sens1', u'IdVehiculeUtilise1', u'Fait1',\
u'HeurePrevue1', u'HeureDebutTrajet1', u'NoDemande2', u'NoUsager2', u'Sens2',\
u'IdVehiculeUtilise2', u'Fait2', u'HeurePrevue2', u'HeureDebutTrajet2']
frame1 = frame1[[u'NoDemande1', u'Fait1',u'HeurePrevue1', u'NoDemande2',u'Fait2',\
u'HeurePrevue2']]
接下来做一些比较,以查看在给定行中该行是否重复该行:
frame2 = frame1[['NoDemande1','NoDemande2','HeurePrevue1','HeurePrevue2']].diff()
frame2['lastColumnsPartner'] = (frame2.NoDemande1 == 1) & (frame2.NoDemande2 == 1) &\
(frame2.HeurePrevue1 == pd.Timedelta(0)) &\
(frame2.HeurePrevue2 == pd.Timedelta(0))
frame2 = frame2['lastColumnsPartner'].to_frame()
frame1 = pd.merge(frame1,frame2,left_index=True,right_index=True)
现在检查Fait
:
frame1['Fait1Pos'] = 0
frame1['Fait2Pos'] = 0
frame1.ix[frame1.Fait1>0,'Fait1Pos'] = 1
frame1.ix[frame1.Fait2>0,'Fait2Pos'] = 1
frame1['FaitPos'] = frame1.Fait1Pos+frame1.Fait2Pos
frame1['FaitBool'] = (frame1.Fait1 > 0)|(frame1.Fait2 > 0)
迭代所有行并使用布尔lastColumnsPartner
创建一个标识重复行的新索引:
frame1['newIndex'] = 0
j = -1
for i,row in frame1.iterrows():
if frame1.ix[i,'lastColumnsPartner'] == False:
j+=1
frame1.ix[i,'newIndex'] = j
仅采用Fait
(FaitBool
)中至少有一个正值的行,按Fait
(FaitPos
)的正值数排序,删除重复项({ {1}})仅保留newIndex
的最高值,然后返回Fait
。
NoDemande
最后在初始帧上使用布尔索引来过滤所有内容。
tokeep = frame1[frame1.FaitBool][['NoDemande1','newIndex','FaitPos']]\
.sort_values('FaitPos',ascending=False).drop_duplicates('newIndex')['NoDemande1']
我无法确定它是否适用于所有情况,它适用于您的示例。也有改进的余地。