1
votes

Création d'un dictionnaire profondément imbriqué à partir d'un fichier csv à l'aide de Python

Je crée un dictionnaire imbriqué à plusieurs niveaux en lisant un gros fichier csv. Le contenu des fichiers est au format suivant, qui stocke les informations pertinentes relatives à un livre unique. Nous pouvons supposer que chaque ligne a 6 colonnes (auteur, titre, année, catégorie, url, citations); toutes les entrées de colonne ont un formatage identique. Par exemple:

  with open(DATA_FILE, 'r') as data_file:
        data = csv.reader(data_file)

Je veux que la sortie corresponde à la façon dont chaque ligne du fichier csv est analysée, comme suit: * (remarque: le nombre de dictionnaires imbriqués dépend des catégories de livres sous l'en-tête de catégorie du csv. Les clés sont basées sur des catégories successives (l'ordre compte), séparées par le délimiteur ":". Pensez à l'ordre des catégories par ligne dans le fichier csv comme répertoire de chemin; plusieurs fichiers peuvent avoir le même répertoire de chemin jusqu'à un certain point ou ils peuvent avoir le même répertoire de chemin et être placés dans le même dossier.

results = {'1973':{
    "magic": {
        "fantasy": {
            "English literature": {
                "name": "goblet of fire",
                "citations": 6,
                "url": "http://doi.acm.org/10.1145/800010.808066"
            }
        },
        "medieval": {
            "name": "The Hobbit",
            "citations": 7,
            "url": "http://doi.acm.org/10.1145/800fdfdffd010.808066"
        }
       }
    },
    '1953':{
    "la": {
        "assessment": {
            "other": {
                "name": "cracking the coding interview",
                "citations": 6,
                "url": "http://doi.acm.org/10.1145/800010.808105"
            }
        }
    }
}
}

Évidemment, certains livres partageront des catégories successives communes, comme dans l'exemple que j'ai montré ci-dessus. Certains livres peuvent également partager exactement les mêmes catégories successives. Je pense que je devrais parcourir de manière récursive la chaîne de catégories par ligne dans le csv, soit créer de nouveaux sous-dictionnaires qui s'écartent d'un ordre de catégorie préexistant, puis créer une représentation dictionnaire du livre une fois qu'il n'y a plus de catégories successives à vérifier. Je ne sais tout simplement pas par où commencer.

Voici ce que J'ai jusqu'ici, c'est juste un setu standard p de lecture des fichiers csv:

Author,Title,Year,Category,Url,Citations
"jk rowling, etc....",goblet of fire,1973,magic: fantasy: english literature,http://doi.acm.org/10.1145/800010.808066,6
"Weiner, Leonard H.",cracking the coding interview,1973,LA: assessment: other,http://doi.acm.org/10.1145/800010.808105,2
"Tolkien",hobbit,1953,magic: fantasy: medieval,http://doi.acm.org/10.1145/800010.808066,6

Essentiellement, je veux créer une représentation arborescente de ce csv en utilisant des dictionnaires imbriqués, le chemin relatif de la catégorie (i.e. magic: fantasy: etc ...), déterminant quel sous-arbre traverser / créer.Si deux livres ou plus ont le même chemin consécutif, je veux faire tous ces livres des feuilles de leur clé respective, au lieu de remplacer chaque livre (feuille) chaque fois qu'un nouveau livre a un chemin de catégorie identique. Les feuilles représentent une représentation par dictionnaire des livres mentionnés par ligne dans le csv.


0 commentaires

3 Réponses :


0
votes
  1. Séparez les catégories par leur emboîtement
  2. Analyser CSV en cadre de données pandas
  3. Regrouper par catégorie dans une boucle
  4. utiliser to_dict () pour convertir en dict dans une boucle groupby

1 commentaires

Je ne peux pas utiliser de dépendances uniquement des méthodes / structures de données intégrées. Le seul module que je peux utiliser est csv.



2
votes

Vous pouvez regrouper vos données par catégorie (à l'aide d'un simple dictionnaire, comme vous l'avez mentionné que vous ne pouvez utiliser aucun module autre que csv ) puis appliquer la récursivité:

{
 "1973": {
    "magic": {
        "fantasy": {
            "english literature": {
                "books": [
                    {
                        "name": "goblet of fire",
                        "citations": "6",
                        "url": "http://doi.acm.org/10.1145/800010.808066",
                        "author": "jk rowling, etc...."
                    }
                ]
            }
        }
    },
    "LA": {
        "assessment": {
            "other": {
                "books": [
                    {
                        "name": "cracking the coding interview",
                        "citations": "2",
                        "url": "http://doi.acm.org/10.1145/800010.808105",
                        "author": "Weiner, Leonard H."
                    }
                ]
            }
        }
    }
 },
 "1953": {
    "magic": {
        "fantasy": {
            "medieval": {
                "books": [
                    {
                        "name": "hobbit",
                        "citations": "6",
                        "url": "http://doi.acm.org/10.1145/800010.808066",
                        "author": "Tolkien"
                    }
                ]
            }
         }
      }
   }
}
import csv
_, *data = csv.reader(open('filename.csv'))
new_data = [[i[3].split(': '), *i[4:], *i[:3]] for i in data]
_data = {}
for i in new_data:
  if i[-1] not in _data:
    _data[i[-1]] = [i]
  else:
    _data[i[-1]].append(i)

final_result = {a:group(b) for a, b in _data.items()}

Sortie:

{
  "magic": {
    "fantasy": {
        "english literature": {
            "books": [
                {
                    "name": "goblet of fire",
                    "citations": "6",
                    "url": "http://doi.acm.org/10.1145/800010.808066",
                    "author": "jk rowling, etc...."
                }
            ]
        },
        "medieval": {
            "books": [
                {
                    "name": "hobbit",
                    "citations": "6",
                    "url": "http://doi.acm.org/10.1145/800010.808066",
                    "author": "Tolkien"
                }
            ]
        }
    }
},
"LA": {
    "assessment": {
        "other": {
            "books": [
                {
                    "name": "cracking the coding interview",
                    "citations": "2",
                    "url": "http://doi.acm.org/10.1145/800010.808105",
                    "author": "Weiner, Leonard H."
                }
            ]
         }
      }
   }
}

Edit: regroupement par date de publication:

import json
print(json.dumps(group(new_data), indent=4))

Sortie:

import csv
_, *data = csv.reader(open('filename.csv'))
new_data = [[i[3].split(': '), *i[4:], *i[:3]] for i in data]
def group(d):
  _d = {}
  for a, *b in d:
    if a[0] not in _d:
      _d[a[0]] = [[a[1:], *b]]
    else:
      _d[a[0]].append([a[1:], *b])
  r = {a:{'books':[{'name':c[-2], 'citations':c[2], 'url':c[1], 'author':c[3]} for c in b if not c[0]], **(lambda x:{} if not x else group(x))([c for c in b if c[0]])} for a, b in _d.items()}
  return {a:{c:d for c, d in b.items() if d} for a, b in r.items()}


16 commentaires

Je continue de recevoir "Erreur d'index: index de liste hors de portée" lors de l'implémentation du premier extrait?


@KaiLee Veuillez publier les données que vous utilisez qui soulèvent cette erreur.


j'ai posté l'extrait


@KaiLee Veuillez consulter ma récente modification.


putain, je reçois toujours des erreurs d'index de liste hors de portée.


@KaiLee Strange, cela fonctionne très bien pour moi. Veuillez créer un gist public , ajouter le contenu de votre fichier entier et publier le lien sous forme de commentaire. Je vais y jeter un œil et voir ce qui peut être fait.


Merci beaucoup! lien


@KaiLee Merci beaucoup. L ' IndexError est dû au fait qu'il existe un cas de pointe majeur dans vos données: certaines catégories de livres ont à la fois des listes de livres régulières associées, ainsi que d'autres catégories enfants, qui doivent toutes deux être incluses dans les données. En tant que tel, j'ai ajouté une clé supplémentaire au résultat final, "books" . Cette clé stocke tous les livres associés à la catégorie parente et permet toujours d'inclure également les catégories enfants. Veuillez voir ma récente modification.


Merci beaucoup! Une dernière chose si cela ne vous dérange pas, pouvez-vous également ajouter les livres «auteurs» comme une autre paire valeur / clé dans le dictionnaire final (par exemple: feuille), pour que j'aie accès aux auteurs, nom, URL et citations des livres?


@KaiLee Pas de problème. Veuillez voir ma récente modification.


Si je devais commander le dictionnaire imbriqué en fonction de la date de publication (c'est-à-dire: la date de publication serait la première clé de chaque dictionnaire de profondeur 1, puis suivie du même ordre que la solution précédente pour les sous-arbres ou profondeur> = 2, comment ferais-je tel?


@KaiLee Essayez-vous simplement d'ajouter la date de publication au dictionnaire avec nom , url , citation etc., ou essayez-vous de regrouper les livres par date de publication? Si vous essayez d'accomplir ce dernier, veuillez publier le résultat souhaité.


par exemple, si deux livres étaient des frères de la version précédente (puisqu'ils partagent des chemins de catégorie identiques), ils ne seraient pas nécessairement frères dans cette version s'ils ne partagent pas la même date de publication.


J'ai modifié la sortie souhaitée dans la question d'origine comme souhaité.


@KaiLee Merci, désolé pour la réponse tardive. Veuillez voir ma récente modification.


@KaiLee Si cette réponse vous a aidé, veuillez l'accepter



0
votes

Vous pouvez faire quelque chose comme ceci:

cols_no_categ = list(df.columns)
cols_no_categ.remove('Category')
category = df['Category']
DICT = {}
for c in category:
    dicto = df[df.Category == c, cols_no_categ].to_dict()
    s = c.split(': ')
    DICT[s[0]][s[1]][s[2]] = dicto

Ensuite, vous voulez isoler la colonne Category et diviser son contenu avec des colonnes:

XXX


0 commentaires