2017-07-17 1 views
1

ich mit einem Multi-Index (Land, Jahr) Datenrahmen in Pandas zu jeweiligen Preisen enthalten BIP-Daten in Landeswährung Einheiten arbeite, zBComputing BIP-Deflatoren über zwei Indizes

   gdp 
country year  
AUS  2013 274865000000  
     2012 269562000000  
     2011 251727000000  
     2010 233604000000  
     2009 221002000000  
     2008 202260000000  
USA  2013 2550000000000 
     ...  ... 

Ich mag wäre erstellen neue Spalte des BIP-Deflators mit 2010 als Basisjahr enthält, zB

   gdp    gdpdef 
country year  
AUS  2013 274865000000 1.18 
     2012 269562000000 1.15 
     2011 251727000000 1.08 
     2010 233604000000 1.00 
     2009 221002000000 0.95 
     2008 202260000000 0.87 
USA  2013 2550000000000 1.01 
     ...  ...    ... 
     2010 2520000000000 1 
     .... ...    ... 

Wo, zu explizit zu sein, wobei jeder Eintrag in „gdpdef“ durch das Verhältnis des BIP gegeben i für Land im Jahr t zum BIP für Land ich im Jahr 2010.

Für ein einzelnes Land mit dem einzigen Index (Jahr) Ich bin in der Lage, dieses Ziel mit erreichen:

base_year = df.get_value(2010, "gdp") 
df["gdpdef"] = df["gdp"].div(base_year) 

Jedoch habe ich über die beiden Indizes um diesen Vorgang viel Mühe, habe replizierende (Land, Jahr) in einer prägnanten Art und Weise. Jede Hilfe zu diesem Zweck wird sehr geschätzt.

Antwort

0

Sie dict für Kartenindex von rename erstellen oder Spalte von map kartieren.

Multiindex kompliziert es. Verwenden Sie also in der ersten Lösung reset_index mit level=1 für die Spalte year und filtern Sie dann nach boolean indexing mit loc für die ausgewählte Spalte gdp.

In der zweiten Lösung ist kein level=1 Parameter, so dass alle Indexstufen in Spalten konvertiert werden. Also dann ist notwendig set_index. Zuletzt wurde values hinzugefügt, weil verschiedene Indizes in df1 und df, so Daten nicht ausgerichtet sind.

print (df) 
         gdp 
country year    
AUS  2013 274865000000 
     2012 269562000000 
     2011 251727000000 
     2010 233604000000 
     2009 221002000000 
     2008 202260000000 
USA  2013 2550000000000 
     2010 2546000000000 

df1 = df.reset_index(level=1) 
d = df1.loc[df1['year'] == 2010, 'gdp'].to_dict() 
print (d) 
{'USA': 2546000000000, 'AUS': 233604000000} 

df["gdpdef"] = df["gdp"].div(df1.rename(index=d).index) 
print (df) 
         gdp gdpdef 
country year       
AUS  2013 274865000000 1.176628 
     2012 269562000000 1.153927 
     2011 251727000000 1.077580 
     2010 233604000000 1.000000 
     2009 221002000000 0.946054 
     2008 202260000000 0.865824 
USA  2013 2550000000000 1.001571 
     2010 2546000000000 1.000000 

df1 = df.reset_index() 
d = df1[df1['year'] == 2010].set_index('country')['gdp'].to_dict() 
print (d) 
{'USA': 2546000000000, 'AUS': 233604000000} 

df["gdpdef"] = df1["gdp"].div(df1['country'].map(d)).values 
print (df) 
         gdp gdpdef 
country year       
AUS  2013 274865000000 1.176628 
     2012 269562000000 1.153927 
     2011 251727000000 1.077580 
     2010 233604000000 1.000000 
     2009 221002000000 0.946054 
     2008 202260000000 0.865824 
USA  2013 2550000000000 1.001571 
     2010 2546000000000 1.000000 

Lösung mit groupby und benutzerdefinierte Funktion sollte durch slowier in großen DataFrame:

def f(x): 
    x['gdpdef'] = x['gdp'].div(x.loc[x.index.get_level_values('year') == 2010, 'gdp'].item()) 
    return x 

df = df.groupby(level='country').apply(f) 
print (df) 
         gdp gdpdef 
country year       
AUS  2013 274865000000 1.176628 
     2012 269562000000 1.153927 
     2011 251727000000 1.077580 
     2010 233604000000 1.000000 
     2009 221002000000 0.946054 
     2008 202260000000 0.865824 
USA  2013 2550000000000 1.001571 
     2010 2546000000000 1.000000 
+0

Tausend Dank Jezrael, sehr informative Antwort. –

+0

@ Ff.Graeme - Froh kann helfen! – jezrael

0

Verwenden Sie die groupby-Funktion in Pandas. Soweit ich weiß, wollen Sie den Deflator für 2010 für jedes Land einzeln nach Ländern anwenden. Dies würde zur Folge haben:

grouped = df.groupby("country") 
for name, group in grouped: 
    group["gdpdef"] = group["gdp"].div(base_year)