0
votes

De la liste des listes à la liste des listes des listes

J'ai une liste comme celle-ci:

new_list = [ [ [45.4, 9.1] ],                               # All coords for 1.
             [ [45.5, 9.1], [45.4, 9.2], [45.4, 9.2] ],     # All coords for 2.
             [ [45.4, 9.1], [45.4, 9.1], [45.4, 9.2] ] ]    # All coords for 3.

Je souhaite utiliser la fonction folio HeatMapWithTime , et pour ce faire, je dois regrouper les données ci-dessus en fonction de le premier élément de chaque sous-liste (1., 2., 3. ecc):

first_list = [[ 1.        , 45.4,  9.1],
              [ 2.        , 45.5,  9.1],
              [ 2.        , 45.4,  9.2],
              [ 2.        , 45.4,  9.2],
              [ 3.        , 45.4,  9.1],
              [ 3.        , 45.4,  9.1],
              [ 3.        , 45.4,  9.1] ]

Comment puis-je faire cela?


0 commentaires

5 Réponses :


3
votes

En supposant que la liste soit triée par les premiers éléments, comme il semble, vous pouvez utiliser itertools.groupby :

from itertools import groupby
from operator import itemgetter
[[i[1:] for i in v] for k,v in groupby(first_list, itemgetter(0))]

#[[[45.4, 9.1]],
# [[45.5, 9.1], [45.4, 9.2], [45.4, 9.2]],
# [[45.4, 9.1], [45.4, 9.1], [45.4, 9.1]]]


0 commentaires

1
votes

Une façon de faire cela est de commencer par trier votre liste:

first_index = None
final_lst = []
for i in lst_data:
    if i[0] != first_index:
        final_lst.append([])
        first_index = i[0]
    final_lst[-1].append(i[1:])

Et ensuite de faire une boucle dessus, en créant un nouveau ljst lorsque le premier index change:

lst_data = sorted(first_list)


0 commentaires

1
votes

J'utiliserais un dict pour cela, vous voudrez peut-être le ramener dans une liste, si vous en avez besoin sous forme de liste, mais utiliser un dict pour le regroupement est généralement utile:

#dict:
{1.0: [[45.4, 9.1]], 2.0: [[45.5, 9.1], [45.4, 9.2], [45.4, 9.2]], 3.0: [[45.4, 9.1], [45.4, 9.1], [45.4, 9.1]]}
#list:
[[[45.4, 9.1]], [[45.5, 9.1], [45.4, 9.2], [45.4, 9.2]], [[45.4, 9.1], [45.4, 9.1], [45.4, 9.1]]]

Sortie:

first_list = [[ 1.        , 45.4,  9.1],
              [ 2.        , 45.5,  9.1],
              [ 2.        , 45.4,  9.2],
              [ 2.        , 45.4,  9.2],
              [ 3.        , 45.4,  9.1],
              [ 3.        , 45.4,  9.1],
              [ 3.        , 45.4,  9.1] ]
result = dict()
for group, *values in first_list:
    if group not in result:
        result[group] = [values]
    else:
        result[group].append(values)
print(result)
### if you want it back as a list:
result_list = [v for k,v in result.items()]
print(result_list)


0 commentaires

2
votes

Vous pouvez rassembler toutes les coordonnées dans un dictionnaire:

>>> [res[key] for key in sorted(res.keys())]
[[[45.4, 9.1]],
 [[45.5, 9.1], [45.4, 9.2], [45.4, 9.2]],
 [[45.4, 9.1], [45.4, 9.1], [45.4, 9.1]]]

Cela vous donne:

>>> list(res.values())
[[[45.4, 9.1]],
 [[45.5, 9.1], [45.4, 9.2], [45.4, 9.2]],
 [[45.4, 9.1], [45.4, 9.1], [45.4, 9.1]]]

Si votre liste était déjà triée, convertissez les valeurs dans une liste (Python 3.6+ uniquement):

>>> res
{1.0: [[45.4, 9.1]],
 2.0: [[45.5, 9.1], [45.4, 9.2], [45.4, 9.2]],
 3.0: [[45.4, 9.1], [45.4, 9.1], [45.4, 9.1]]}

Sinon, vous devez d'abord les trier:

res = {}
for entry in first_list:
    res.setdefault(entry[0], []).append(entry[1:])

p>


2 commentaires

"Si votre liste a déjà été triée, convertissez les valeurs en une liste" En êtes-vous sûr? Je pensais que les dictionnaires ne préservaient pas l'ordre


À partir de Python 3.6, l'ordre d'insertion do conserve. stackoverflow.com/questions/39980323 /…



0
votes

Une solution utilisant pandas , un choix judicieux face à des formats de données complexes:

import pandas as pd    
pd.DataFrame(first_list).set_index(0).groupby(df.index).apply(lambda x: x.values.tolist()).tolist()
#-> 
[[[45.4, 9.1]],
 [[45.5, 9.1], [45.4, 9.2], [45.4, 9.2]],
 [[45.4, 9.1], [45.4, 9.1], [45.4, 9.1]]]


6 commentaires

Super, j'utilise des pandas, donc je suis revenu au df d'origine et j'ai exécuté cette commande: heat_list = df.groupby (df.day) .apply (lambda x: x.values.tolist ()). Tolist () . La sortie renvoie une sous-sous-liste comme celle-ci: [1.0, 45.44430542, 9.16762733] , mais je ne veux pas du premier élément, seulement lat et lon. Comment puis je faire ça?


@Ibarrond pandas peut être vraiment utile, mais je pense que cette solution est très complexe (difficile à déboguer à l'avenir) et je soupçonne qu'elle pourrait être assez lente


Je suis d'accord, mais j'utilise très souvent Pandas, c'est pourquoi j'aimerais résoudre le problème de cette manière.


@Nathan si vous exécutez chaque opération étape par étape, vous pouvez la déboguer incroyablement facilement. Performance WRT, à moins que la question ne le demande, il ne sert à rien de fournir une solution ultrarapide, mais plutôt une solution compréhensible et réutilisable.


@alcor J'essaierais quelque chose comme ceci: heat_list = df.groupby (df.day) .apply (lambda x: x.values ​​[1:]. tolist ()). tolist () . (Notez le [1:] pour supprimer le premier élément)


@ibarrond Je programme en python depuis plusieurs années maintenant et il m'a fallu une seconde pour comprendre ce que fait votre fonction. Ayant dû travailler sur du code hérité contenant de nombreux exemples de telles solutions, je ne suis pas d'accord poliment sur la facilité de trouver (et de résoudre) de telles erreurs.