2017-10-16 6 views
0

J'ai trouvé toutes les valeurs et tout et j'ai essayé de trier, mais il trie séparément plutôt qu'ensemble. Je veux trier par années, et les notes devraient juste suivre les valeurs des années. Cependant, quand je fais le tri (années), cela ne ferait que trier les années, laissant les notes telles quelles.Trier les valeurs à partir de deux tableaux différents

lorsque l'ouverture du fichier, il me donnerait quelque chose comme:

Year,Grade 
2000,84 
2001,34 
2002,82 
2012,74 
2008,90 

et ainsi de suite. J'ai donc calculé la moyenne et tout.

years, average_grades = [],[] 
avg = [] 
d = {} 

with open(file,'r') as f: 
    next(f) 
    for line in f: 
     year, grade = (s.strip() for s in line.split(',')) 
     if year in d: 
      d[year][0] += int(grade) 
      d[year][1] += 1 
     else: 
      d[year] = [int(grade),1] 

    for year, grades in d.items(): 
     years.append(str(year)) 
     average_grades.append(float(grades[0])/grades[1]) 

    return years, average_grades 

Sans sorte, il me donnerait semblable à ceci:

2001 74.625 
2006 72.241 
2012 70.875 
2017 69.1981 
2005 72.5 
2008 71.244 
2014 73.318 
2004 72.1 
2007 72.88 
2000 73.1 

With years.sort(), it would give me similar to this: 
2000 74.625 
2001 72.241 
2002 70.875 
2003 69.1981 
2004 72.5 
2005 71.244 
2006 73.318 
2007 72.1 

Donc, le genre ne fonctionnera que pendant des années, mais ne le ferai pas pour les grades. Ce problème m'inquiète depuis si longtemps maintenant. Je ne prévois pas d'utiliser des pandas.

+0

Pouvez-vous poster un exemple de données –

+0

je fourni des données par exemple. – Mayjunejuly

+0

Le problème est que vous renvoyez deux structures de données _independent_. Les 'years' et' average_grades' retournés ne sont pas liés lorsque vous les renvoyez. – Unapiedra

Répondre

0

Vous voulez ajouter cette ligne avant la déclaration de retour:

years, average_grades = zip(*sorted(zip(years, average_grades), key=lambda p: p[0])) 

Qu'est-ce que cela fait?

Le zip(years, average_grades) intérieur indique à python de mettre en place chaque élément des itérables years et average_grades sous la forme d'un tableau de tuples. Utilitaire

sorted(..., key=lambda p: p[0]) est l'utilitaire sorted, sauf que maintenant qu'il fonctionne sur la paire, il doit savoir comment trier la paire. Nous passons donc une fonction lambda qui dit "regarde la première partie".

Le zip(*...) externe prend les résultats renvoyés par le trié, qui est une liste de tuples, et le convertit en deux listes. Le * lui dit de traiter la liste comme un tas d'arguments, donc vous passez par paire à zip. zip prend n'importe quel nombre d'arguments de tuple, et les divise en ses composants. Dans ce cas, il prend les dix paires et le divise en 2 tuples de 10 chacun.

Tant que vos itérations sont de la même longueur, il s'agit d'un mécanisme «de base» pour les trier.

+0

Pas une bonne réponse: Si OP a le contrôle sur le code affiché, il est beaucoup plus propre de garder ensemble les tuples '(année, année)'. Puis trier, puis dé-zipper. Pas de downvote cependant. – Unapiedra

+0

La seule différence entre maintenir les variables séparément et les compresser est l'utilisation de zip. Il y a beaucoup d'exemples concrets où vous aurez deux ensembles de données distincts. @Unapiedra, s'il vous plaît rappelez-vous l'objectif de Stack Overflow est de créer un référentiel de connaissances pour les futurs utilisateurs. Il est valable d'affirmer que dans ce cas, ne pas séparer les deux listes serait la meilleure solution; il n'est pas correct de prétendre qu'une réponse qui fournit suffisamment d'informations pour aider les futurs questionneurs n'est pas une «bonne réponse» en raison d'une implémentation que vous fournissez pour cette instance spécifique. –

1

Utilisez zip pour les joindre en tant que tuple puis sort.

Exemple:

>>> y = [3, 2, 4, 1, 2] 
>>> g = [0.1, 0.4, 0.2, 0.7, 0.1] 

>>> mix = list(zip(y,g)) 
>>> mix 
=> [(3, 0.1), (2, 0.4), (4, 0.2), (1, 0.7), (2, 0.1)] 

>>> sorted(mix) 
=> [(1, 0.7), (2, 0.1), (2, 0.4), (3, 0.1), (4, 0.2)] 

#print dans votre commande:

>>> for ele in sorted(mix): 
     print(ele[0],ele[1]) 

1 0.7 
2 0.1 
2 0.4 
3 0.1 
4 0.2 

Remarque que pour l'année 2, il y a deux valeurs de 0.1 et 0.4 et qu'il le gère donnant plus de préférence à la year et la suivante grades.

0

J'espère que cet exemple sera utile, donc:

years = [2001,2000,2002] 
average_grades = [5,10,15] 
result = zip(years,average_grades) 
for item in sorted(result, key=lambda x: x[0]): 
    print('{} {}'.format(*item)) 
#2000 10 
#2001 5 
#2002 15 
0

Les solutions alternatives prennent les résultats et les passer comme un éclair ensemble. Comme vous semblez avoir le contrôle de la lecture du fichier, je suggère à la place de ne jamais séparer les années et les notes. À mon avis, cela est plus facile que plus tard, combinant les deux listes avec le code postal.

years, average_grades = [],[] 
avg = [] 
d = {} 

with open(file,'r') as f: 
    next(f) 
    for line in f: 
     year, grade = (s.strip() for s in line.split(',')) 
     if year in d: 
      d[year][0] += int(grade) 
      d[year][1] += 1 
     else: 
      d[year] = [int(grade),1] 

# Iterator-Expression to convert 'd' dictionary into list of tuples. 
# Puts (year, average grade) into a new list. 
year_grade = [(year, float(grade_tuple[0])/grade_tuple[1]) \ 
       for year, grade_tuple in d.items()] 

# Sorting is optional, if you return the list of tuples. 
# Use 'key=lambda ...' to sort over the year (the first element of the tuple). 
# Technically, specyfing the 'key' is not necessary as the default would be 
# to sort over the first element first. 
year_grade.sort(key=lambda x: x[0]) 

return year_grade 
# Alternatively, return the list of tuples as a list of two tuples: years, grades 
return zip(*year_grade) 

Autres améliorations

Vous pouvez utiliser un defaultdict pour éviter le bloc if year in d:

from collections import defaultdict 

d = defaultdict(lambda: [0, 0]) 

with open(fname,'r') as f: 
    next(f) 
    for line in f: 
     year, grade = (s.strip() for s in line.split(',')) 
     d[year][0] += int(grade) 
     d[year][1] += 1 

    def avg(t): 
     return float(t[0])/t[1] 
    year_grade = [(y, avg(g)) for y, g in d.items()] 
    year_grade.sort() 

    return zip(*year_grade) # Python3: tuple(zip(*year_grade))