2016-11-04 5 views
2

ich mit einem Multiindex Dataframe arbeite und wollen mehrere Operationen tun, mit denen ich zu kämpfen:Operationen innerhalb Multiindex Datenrahmen

a) Ich möchte mehrere Operationen auf eine Liste (elementweise) anzuwenden, ohne für die Verwendung von Schleifen

b) Ich möchte die Werte der Indizes meines DataFrame extrahieren und diese Werte vergleichen; bevor sie vom Objekt umgewandelt werden in int oder Float

c) I innerhalb der Datenrahmen auf die Vergleichswerte werden soll (ohne Schleifen verwendet wird), und wählen Werte von entweder Spalte auf dem Wert dieses Vergleichs abhängig

= ================================================= =====================

import pandas as pd 
import numpy as np 

idx = pd.IndexSlice 
ix = pd.MultiIndex.from_product(
    [['2015', '2016', '2017', '2018'], 
    ['2016', '2017', '2018', '2019', '2020'], 
    ['A', 'B', 'C']], 
    names=['SimulationStart', 'ProjectionPeriod', 'Group'] 
) 

df = pd.DataFrame(np.random.randn(60, 1), index=ix, columns=['Origin']) 
origin = df.loc[idx[:, :, :], 'Origin'].values 

increase_over_base_percent = 0.3 
increase_over_base_abs = 10 
abs_level = 1 
min_increase = 0.001 

'Is there a way to do this comparison without using for loops?' 
# The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 
change = pd.Series(np.nan) 
i = 0 
for element in origin: 
    change[i] = max(
     min(element * (1 + increase_over_base_percent), 
      element + increase_over_base_abs, 
      abs_level), 
     element + min_increase) 
    i += 1 

print(change) 


# Write results to a new column in the DataFrame ('Change') 
df.loc[idx[:, :, :], 'Change'] = change 

# Add data on 'Group' level 
group_qualifier = [0, 0, 1] 

# Is there a way to apply the group_qualifier to the group level without having to slice each index? 
# Note: the formula does not work yet (results are to be reported in a new column of the DataFrame) 
df.loc[idx[:], 'GroupQA'] = group_qualifier 

'This is the part I am struggling with most (my index values are objects, not integers or floats;' 
'and the comparison of values within the DataFrame does not work either)' 
# Create new column 'Selected'; use origin values for all combinations where 
# projectionPeriod < simulationStart & group_qualifier value == 0; 
# use change values for all other combinations 
values = df.index.get_level_values 
mask = (values('ProjectionPeriod') - values('SimulationStart')) <= 1 
mask = mask * df.loc[idx[:], 'GroupQA'].values 
selected = df.loc[mask] 
df.loc[idx[:, :, :], 'Selected'] = selected 
+0

In Bezug auf (a), sehe ich nicht die for-Schleife, die Sie vermeiden möchten. – IanS

+0

@IanS - Entschuldigung für die Verwirrung. Ich habe den Code bearbeitet, um die For-Schleife wiederzugeben, über die ich gesprochen habe. – Andreas

+0

Danke für die Annahme meiner Antwort. Brauchst du Hilfe mit den anderen Gegenständen? – IanS

Antwort

2

eine Teilantwort für a):

df['Change'] = pd.concat([ 
    pd.concat([ 
     df.loc[:, 'Origin'] * (1 + increase_over_base_percent), 
     df.loc[:, 'Origin'] + increase_over_base_abs, 
    ], axis=1).min(axis=1).clip(upper=abs_level), 
    df.loc[:, 'Origin'] + min_increase 
], axis=1).max(axis=1) 

Die Idee ist uns e pandas 'min und max Funktionen direkt auf der Origin Serie (mit einem kleinen Twist, mit clip für abs_level).

Da Pandas-Operationen den Index beibehalten, können Sie das Ergebnis direkt einer Spalte zuweisen.


Edit: Wenn Sie möchten, können Sie die combine Ansatz am Ende des this question verwenden erläutert.

Verwandte Themen