2017-09-15 3 views
0

J'essaie de trouver un moyen d'importer un fichier .txt idéalement en tant que données (pandas) en utilisant python 3.5. Je l'ai fait quelques fois avec des données différentes. Ce fichier a quelques milliers de cas/cas, qui prennent chacun 13 lignes suivies par une ligne blanche:Importer un fichier txt avec plus d'une ligne par instance en utilisant python

Cat1: text 
… 
Cat13: text 

Cat1: text 
… 
Cat13: text … 

En utilisant le code suivant, je peux accéder à chaque ligne et de créer un nouveau vecteur par exemple (malheureusement comme vecteur colonne au lieu de vecteur ligne, ce qui pourrait être ajouté à une nouvelle trame de données):

import codecs 
import pandas as pd 
with codecs.open(‚file.txt', 'r',encoding='utf-8', errors='ignore') as f: 
    lines = f.readlines() 

L = list(lines[i] for i in range(14)) 
se = pd.Series(L[:13]) 
df = pd.DataFrame([], columns=('Cat1’,…,’Cat13‘)) 
df['new_row'] = se.values 

Je suis à la recherche d'une trame de données de base (cas x 13) avec « Cat1 », ..., « CAT13 » sous forme de colonnes et instances en tant que lignes.

Cat1 Cat2 ... Cat13 
text text  text 
text text  text 
... 

Y at-il une solution facile à ce problème ou même un autre paquet pour charger un tel fichier?

modifier: Je ne savais pas vraiment ce que je cherchais. Enfin a été en mesure de résoudre ce problème en utilisant itertools.groupby, qui a été mentionné dans this thread.

import itertools 
import codecs 
import pandas as pd 

def group_separator(line): 
    return line=='\n' 

with codecs.open('file.txt', 'r',encoding='utf-8', errors='ignore') as f: 
    lines = f.readlines() 

cols = ('Cat1',...,'Cat13') 
data = [] 
for (key, group) in itertools.groupby(lines, group_separator): 
    if key: 
     next(group).strip() 
    else: 
     tem_data = [i.strip() for i in group] 
     tem_data = filter(lambda l: l != '', tem_data) 
     tem_data = [i.split(':',1) for i in tem_data] 
     tem_data = [i[1].strip() for i in tem_data] 
     if len(tem_data) == 13: 
      data.append(tem_data) 

df = pd.DataFrame(data, columns=cols) 
+2

Pouvez-vous s'il vous plaît modifier vos données d'exemple pour montrer certains cas, complet et les résultats escomptés? – zipa

+0

Et d'être plus idiomatique. – GiantsLoveDeathMetal

+0

@tsc vérifier ma réponse ci-dessous – MedAli

Répondre

0

donné ce format du fichier d'entrée:

Cat1/instance1: text … 
Cat13/instance1: text 

Cat1/instance2: text … 
Cat13/instance2: text … 

Vous pouvez lire le fichier en tant que trame de données d'une colonne comme suit (ps: pandas géants seront sauter automatiquement les lignes vides):

In [70]: df = pd.read_csv('/tmp/test.txt', header=None) 

In [71]: df 
Out[71]: 
         0 
0 Cat1/instance1: text … 
1 Cat13/instance1: text 
2 Cat1/instance2: text … 
3 Cat13/instance2: text … 

In [72]: 

La division des lignes basée sur / ou : pour construire une nouvelle trame de données avec trois colonnes:

In [72]: dff = pd.DataFrame(df[0].str.strip().str.split('/|: ').tolist()) 

In [73]: dff 
Out[73]: 
     0   1  2 
0 Cat1 instance1 text … 
1 Cat13 instance1 text 
2 Cat1 instance2 text … 
3 Cat13 instance2 text … 

In [74]: 

Définissez ensuite les deux premières colonnes [0, 1], comme un index dff, Désempiler le dataframe avec le premier niveau de l'indice pour faire cat1..cat13 que les nouvelles colonnes. puis reset_index pour enlever le instance1.. instance2 avec une ligne:

In [74]: dff = dff.set_index([0,1]).unstack(level=0).reset_index(drop=True) 

In [75]: dff 
Out[75]: 
     2   
0 Cat1 Cat13 
0 text … text 
1 text … text … 

In [76]: 

Et enfin, il faut supprimer le niveau uncessary dans les colonnes et ne garder que cat1... cat13

In [76]: dff.columns = dff.columns.levels[1].tolist() 

In [77]: dff 
Out[77]: 
    Cat1 Cat13 
0 text … text 
1 text … text … 

In [78]: 

Sans les explications ci-dessus, la le code global ressemble à ceci:

df = pd.read_csv('/tmp/test.txt', header=None) 
dff = pd.DataFrame(df[0].str.strip().str.split('/|: ').tolist()) 
dff = dff.set_index([0,1]).unstack(level=0).reset_index(drop=True) 
dff.columns = dff.columns.levels[1].tolist() 

Si vous souhaitez gérer coder utf-8, lisez le fichier comme suit:

df = pd.read_csv('/tmp/test.txt', header=None, encoding='utf-8') 
+0

Thx pour votre réponse! J'ai réussi à charger les données via: les codecs d'importation fichier = codecs.open ('fichier.txt', 'rU', 'UTF-8', erreurs = 'ignore') df = pd.read_csv (file, header = Aucun, sep = '\ n'). En utilisant votre code pour diviser les données, j'ai eu 2 colonnes cat1 ..cat13 et "texte". Toute contribution sur la façon d'agréger les données? – tsc

+0

@tsc que voulez-vous dire en agrégeant les données? Pouvez-vous donner un exemple? Aussi, si ma réponse était suffisante pour votre question initiale, envisagez de l'accepter et peut-être de voter;) – MedAli