2009-11-18 4 views
0

I ont un ensemble de données similaire à ceci:Comment fusionner les doublons dans les tableaux de python 2D

# Start_Time End_Time  Call_Type Info 
1 13:14:37.236 13:14:53.700 Ping1  RTT(Avr):160ms 
2 13:14:58.955 13:15:29.984 Ping2  RTT(Avr):40ms 
3 13:19:12.754 13:19:14.757 Ping3_1 RTT(Avr):620ms 
3 13:19:12.754    Ping3_2 RTT(Avr):210ms 
4 13:14:58.955 13:15:29.984 Ping4  RTT(Avr):360ms 
5 13:19:12.754 13:19:14.757 Ping1  RTT(Avr):40ms 
6 13:19:59.862 13:20:01.522 Ping2  RTT(Avr):163ms 
... 

Quand je parse à travers elle, je dois fusionner les résultats de Ping3_1 et Ping3_2, prendre la moyenne de ceux deux lignes et l'exportation que d'une ligne, de sorte que la fin du résultat serait comme ceci:

# Start_Time End_Time  Call_Type Info 
1 13:14:37.236 13:14:53.700 Ping1  RTT(Avr):160ms 
2 13:14:58.955 13:15:29.984 Ping2  RTT(Avr):40ms 
3 13:19:12.754 13:19:14.757 Ping3  RTT(Avr):415ms 
4 13:14:58.955 13:15:29.984 Ping4  RTT(Avr):360ms 
5 13:19:12.754 13:19:14.757 Ping1  RTT(Avr):40ms 
6 13:19:59.862 13:20:01.522 Ping2  RTT(Avr):163ms 
... 

Actuellement, je concaténer des colonnes 0 et 1 pour faire une clé unique, trouver la duplication là, puis en faisant la reste du traitement spécial pour ces pings parallèles. Ce n'est pas élégant du tout. Je me demande juste quelle est la meilleure façon de le faire. Merci!

+2

Les doublons sont-ils toujours sur des lignes adjacentes? –

Répondre

0

En supposant que les doublons sont adjacents, vous pouvez utiliser un générateur comme celui-ci. Je suppose que vous avez déjà un code à la moyenne des pings

def average_pings(ping1, ping2): 
    pass 

def merge_pings(seq): 
    prev_key=prev_key=None 
    for item in seq: 
     key = item.split()[:2] 
     if key == prev_key: 
      yield average_pings(prev_item, item) 
     else: 
      yield item 
     prev_key=key 
     prev_item=item 
0

Je ne suis pas sûr de la façon dont vos données sont structurées, donc je vais prendre une liste des dicts à des fins de frappe de canard.

Je suppose également que la véritable clé primaire de votre jeu de données est Start.

for i in range(len(dataset)-1): 
    #Detect duplicates, assuming they are sorted properly 
    if dataset[i]["Start"] == dataset[i+1]["Start"]: 
    #Merge 'em 
    dataset[i+1] = merge(dataset[i], dataset[i+1]) 

    #Deleting items from the array you are iterating over is a bad idea 
    dataset[i] = None 

dataset = [item for item in dataset if item != None] #so just delete them later 

... où fusionnerait la fonction qui effectue réellement la fusion.

Pas élégant, C-ish, mais probablement mieux que ce que vous utilisez actuellement.

Ils ne sont pas triés?

dataset.sort((lambda x,y: return cmp(x["Start"],y["Start"]))) 

Maintenant, ils devraient être.

+0

n'utilisez jamais cmp pour trier. c'est plus lent. Utilisez la clé: 'dataset.sort (key = operator.itemgetter ('Start'))' – nosklo

+0

Eh bien, je suppose que je n'aurai pas le choix avec Py3k en tout cas. – badp

1

vos doublons sont supposant adjacentes (comme ils sont indiqués sur votre question), itertools.groupby est le moyen idéal pour les identifier comme des doubles (avec un peu d'aide de operator.itemgetter pour extraire la définition « clé » identité. En supposant que vous avez liste des objets (les pings) avec des attributs tels que .start et .end:

import itertools 
import operator 

def merge(listofpings): 
    k = operator.itemgetter('start', 'end') 
    for i, grp in itertools.groupby(listofpings, key=k): 
    lst = list(grp) 
    if len(lst) > 2: 
     item = mergepings(lst) 
    else: 
     item = lst[0] 
    emitping(i, item) 

supposant que vous avez déjà des fonctions mergepings de fusionner une liste de> 1 « dupliquer » pings et emitping pour émettre un ping numéroté (nu ou fusionné).

Si listofpings n'est pas déjà correctement trié, il suffit d'ajouter listofpings.sort(key=k) juste avant la boucle for (en émettant vraisemblablement dans l'ordre trié, n'est-ce pas?).

Questions connexes