2017-08-16 2 views
1

Ich habe eine CSV-Datei, die ich in einem Pandas DataFrame lesen, die eine Spalte mit mehreren Jahreswerte durch ein Semikolon getrennt enthält.Extrahieren Minimum und Maximum Jahr von Zeichenfolge in Pandas DataFrame

Ich muss den minimalen und maximalen Wert aus der Zeichenfolge extrahieren und jeweils in einer neuen Spalte speichern.

Ich bin in der Lage, das Minimum und Maximum zu drucken, aber ich kann nicht scheinen, die richtigen Werte von jeder Zeile zu erhalten, die in einer neuen Spalte gespeichert werden.

Jede Hilfe wird sehr geschätzt.

Beispieldatenrahmen:

import pandas as pd 
import numpy as np 

raw_data = {'id': ['1473-2262', '2327-9214', '1949-8349', '2375-6314', 
        '0095-6562'], 
      'years': ['2000; 2001; 2002; 2003; 2004; 2004; 2004; 2005', 
         '2003; 2004; 2005', '2015', np.nan, '2012; 2014']} 
df = pd.DataFrame(raw_data, columns = ['id', 'years']) 

Dies ist der Datenrahmen, was ich brauche:

  id           years minyear maxyear 
0 1473-2262 2000; 2001; 2002; 2003; 2004; 2004; 2004; 2005 2000.0 2005.0 
1 2327-9214        2003; 2004; 2005 2003.0 2005.0 
2 1949-8349           2015 2015.0 2015.0 
3 2375-6314            NaN  NaN  NaN 
4 0095-6562          2012; 2014 2012.0 2014.0 

ich das Minimum drucken kann und maximal:

x = df['years'].notnull() 

for row in df['years'][x].str.split(pat=';'): 
    lst = list() 
    for item in row: 
     lst.append(int(item)) 
    print('Min=',min(lst),'Max=',max(lst)) 

Min= 2000 Max= 2005 
Min= 2003 Max= 2005 
Min= 2015 Max= 2015 
Min= 2012 Max= 2014 

Hier ist, wie ich versucht habe, um die Werte zu neuen Spalten zu erfassen:

x = df['years'].notnull() 

for row in df['years'][x].str.split(pat=';'): 
    lst = list() 
    for item in row: 
     lst.append(int(item)) 
    df['minyear']=min(lst) 
    df['maxyear']=max(lst) 

Nur die Werte aus der letzten Zeile werden in den neuen Spalten gespeichert.

   id           years minyear maxyear 
0 1473-2262 2000; 2001; 2002; 2003; 2004; 2004; 2004; 2005  2012  2014 
1 2327-9214        2003; 2004; 2005  2012  2014 
2 1949-8349           2015  2012  2014 
3 2375-6314            NaN  2012  2014 
4 0095-6562          2012; 2014  2012  2014 

Antwort

2

Ich glaube, Sie brauchen str.split mit expand=True für neue DataFrame, dann float gegossen.

Indexwerte sind gleich, so neue Spalten zuweisen:

df1 = df['years'].str.split('; ', expand=True).astype(float) 
df = df.assign(maxyear=df1.max(axis=1),minyear=df1.min(axis=1)) 
#same as 
#df['maxyear'], df['minyear'] = df1.min(axis=1), df1.max(axis=1) 
print (df) 
      id           years maxyear minyear 
0 1473-2262 2000; 2001; 2002; 2003; 2004; 2004; 2004; 2005 2000.0 2005.0 
1 2327-9214        2003; 2004; 2005 2003.0 2005.0 
2 1949-8349           2015 2015.0 2015.0 
3 2375-6314            NaN  NaN  NaN 
4 0095-6562          2012; 2014 2012.0 2014.0 
0

Eine Lösung ähnlich dem von jezrael vorgeschlagen, sondern eine Umwandlung in eine Serie verwenden. Warnung: Diese Lösung skaliert nicht gut.

years = df.years.str.split(";").apply(pd.Series).astype(float)   
#0  1  2  3  4  5  6  7 
#0 2000.0 2001.0 2002.0 2003.0 2004.0 2004.0 2004.0 2005.0 
#1 2003.0 2004.0 2005.0  NaN  NaN  NaN  NaN  NaN 
#2 2015.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN 
#3  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN 
#4 2012.0 2014.0  NaN  NaN  NaN  NaN  NaN  NaN 
df['maxyear'], df['minyear'] = years.min(axis=1), years.max(axis=1) 
+0

Meine Lösung ist nur doppelt so langsam wie Ihre. Nicht so schlecht :) – DyZ

+0

Nein, nur 5. Würde es nicht linear mit der Anzahl der Zeilen skalieren? – DyZ

+0

@jezrael Sie haben Recht. Ich wundere mich warum. – DyZ

Verwandte Themen