python在Pandas条件下删除重复行

2024-05-14 23:10:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这样一个数据帧:

  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),列{}是相同的,这意味着记录被记录两次。我必须删除一对,并且我想在Fait列中保存一个更多的正数(至少有一个大于0)

所以我的结果应该是:

^{pr2}$

我知道这是关于OR逻辑的,但我不知道如何实现它。在

~


Tags: 数据falsedf记录senskeepduplicatedpr2
3条回答

我在这里看到两种解决方案。 第一种方法基于这样一种建议,即在数据集中始终有连续的条目对,即如果任何条目有一对条目,则该对位于该条目之后。然后,您应该循环使用步长为2的数据帧:

for i in range(0,x,2):
  your action

在这个循环中,你可以比较你的两个条目,去掉一个负值。在

我的第二个建议有点复杂。

首先,您应该复制并延迟(按特定行数移动)所有列。这可以通过以下函数实现(仅适用于NoDemande,对于每一列都使用循环):

^{pr2}$

它看起来像:

  NoDemande      NoDemande_lagged

0 42191000823    42191000822
1 42191000822    42191000822 
2 42191000822    42191000823
3 42191000823    42191000834

然后比较NoDemande和NoDemande_lagged列中同一行中的两个值。如果42191000822中的数字比NoDemande中的值大或小1,则比较FaitFait\u lagged并选择更正的值,将其粘贴到新的列Fait\u selected。您应该对其他列执行相同的操作,以便每个列都有一个滞后副本和一个选定副本。之后,您应该删除下一行,因为您已经将它与前一行进行了比较。 最后,您应该删除原始列和滞后列,只保留“\u selected”。在

很抱歉给你一个复杂的解释,希望这对你有帮助。如果你熟悉RapidMiner,我可以在那里解释如何做,这样会更容易。我给了你一些关于各种概念的想法,可以帮助你解决你的问题。在

这是一个冗长的解决方案,可能还有较短的解决方案。frame0正是您在上面发布的框架。在

{2>把第一行的数据分成两行,然后重新组合。使事情更简单:

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']]

接下来进行一些比较,看看在给定行中,该行上面的行是否重复:

^{pr2}$

现在检查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

只取FaitFaitBool)中至少有一个正值的行,按FaitFaitPos)的正数排序,删除重复项(newIndex),只保留Fait的最大值,然后返回NoDemande。在

tokeep = frame1[frame1.FaitBool][['NoDemande1','newIndex','FaitPos']]\
 .sort_values('FaitPos',ascending=False).drop_duplicates('newIndex')['NoDemande1']

最后在初始帧上使用布尔索引过滤所有内容。在

frame0 = frame0[frame0.NoDemande.isin(tokeep)]

我不能确定它是否适用于所有的情况,它适用于你的例子。此外,可能还有改进的余地。在

我处理这个问题的方法是生成两列,其中包含检查的条件(相同的heure和连续递增的NoDemande)。然后迭代数据帧,根据Fait列删除不需要的对。在

这是一个有点骇人听闻的代码,但这似乎能做到:

# 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

结果:

^{pr2}$

相关问题 更多 >

    热门问题