2017-12-30 19 views
2

Ich habe eine CSV-Datei bekommen, die wie folgt aussehen soll:Pandas, verketten bestimmte Spalten, wenn andere Spalten sind leer

ID, years_active, issues 
------------------------------- 
'Truck1', 8, 'In dire need of a paintjob' 
'Car 5', 3, 'To small for large groups' 

jedoch die CSV etwas fehlerhaft ist und sieht derzeit wie folgt aus.

ID, years_active, issues 
------------------------ 
'Truck1', 8, 'In dire need' 
'','', 'of a' 
'','', 'paintjob' 
'Car 5', 3, 'To small for' 
'', '', 'large groups' 

Nun, ich bin durch das Fehlen einer ‚ID‘ fehlerhafte Zeilen identifizieren können und ‚years_active‘ Wert und möchte den Wert von ‚Themen dieser Reihe zum letzten vorhergehenden Zeile, die hatte‘ anhängen ID 'und' Jahre_aktiv 'Werte.

ich sehr bin nicht mit Pandas erlebt, kam aber mit dem folgenden Code auf:

for index, row in df.iterrows(): 
     if row['years_active'] == None: 
      df.loc[index-1]['issues'] += row['issues'] 

Yet - die IF-Bedingung auszulösen ausfällt. Ist das, was ich versuche, möglich? Und wenn ja, hat jemand eine Idee, was ich falsch mache?

Antwort

3

Ihre Abtastwerteingang Gegeben:

new_df = df.groupby(df.ID.replace('', method='ffill')).agg({'years_active': 'first', 'issues': ' '.join}) 

Which'll Sie geben:

 years_active      issues 
ID            
Car 5    3 To small for large groups 
Truck1    8 In dire need of a paintjob 

Also, was wir hier tun, vorwärts füllt

df = pd.DataFrame({ 
    'ID': ['Truck1', '', '', 'Car 5', ''], 
    'years_active': [8, '', '', 3, ''], 
    'issues': ['In dire need', 'of a', 'paintjob', 'To small for', 'large groups'] 
}) 

Sie verwenden können die nicht leeren IDs in nachfolgende leere IDs und diese zum Gruppieren der zugehörigen Zeilen verwenden. Wir aggregieren dann, um das erste Vorkommen des years_active zu nehmen, und verbinden die Ausgaben Spalten in der Reihenfolge, in der sie erscheinen, um ein einzelnes Ergebnis zu erstellen.

+0

Dies löste es, danke! – Jasper

+1

Eine Alternative wäre: 'df.groupby (df.ID.str.len(). Gt (0) .cumsum()). Agg ({'Issues': '' .join, 'years_active': 'first' }) ' –

2

Nach verwendet eine for Schleife Strings zu finden und fügen Sie (Datenrahmen von JonClements' Antwort):

df = pd.DataFrame({ 
    'ID': ['Truck1', '', '', 'Car 5', ''], 
    'years_active': [8, '', '', 3, ''], 
    'issues': ['In dire need', 'of a', 'paintjob', 'To small for', 'large groups'] 
}) 


ss = ""; ii = 0; ilist = [0] 
for i in range(len(df.index)): 
    if i>0 and df.ID[i] != "": 
     df.issues[ii] = ss 
     ss = df.issues[i] 
     ii = i 
     ilist.append(ii) 
    else: 
     ss += ' '+df.issues[i] 
df.issues[ii] = ss 
df = df.iloc[ilist] 
print(df) 

Ausgang:

 ID      issues years_active 
0 Truck1 In dire need of a paintjob   8 
3 Car 5 To small for large groups   3 
1

Es könnte im Zusammenhang mit dieser Frage erwähnenswert sein, dass Es gibt eine oft übersehene Möglichkeit, um peinliche Eingaben zu verarbeiten, indem Sie die StringIO-Bibliothek verwenden.

Der wesentliche Punkt ist, dass read_csv aus einer StringIO-Datei lesen kann.

In diesem Fall ordne ich einfache Anführungszeichen und mehrere Kommas zu verwerfen, die read_csv verwirren würde, und ich hänge Sie die zweiten und die folgenden Zeilen der Eingabe in der ersten Zeile, komplett, Linien read_csv bilden herkömmliche csv zu bilden.

Hier ist, was read_csv empfängt.

 ID years_active      issues 
0 Truck1    8 In dire need of a paintjob 
1 Car 5    3 To small for large groups 

Der Code ist hässlich, aber einfach zu folgen.

import pandas as pd 
from io import StringIO 

for_pd = StringIO() 
with open('jasper.txt') as jasper: 
    print (jasper.readline(), file=for_pd) 
    line = jasper.readline() 
    complete_record = '' 
    for line in jasper: 
     line = ''.join(line.rstrip().replace(', ', ',').replace("'", '')) 
     if line.startswith(','): 
      complete_record += line.replace(',,', ',').replace(',', ' ') 
     else: 
      if complete_record: 
       print (complete_record, file=for_pd) 
      complete_record = line 
if complete_record: 
    print (complete_record, file=for_pd) 

for_pd.seek(0) 

df = pd.read_csv(for_pd) 
print (df) 
Verwandte Themen