2016-08-12 4 views
4

Ich habe DataFrame und ich versuche, alle Werte in jeder Spalte der Summe dieser Spalte zuzuordnen.Zuweisen von Werten in jeder Spalte, um die Summe dieser Spalte zu sein

x = pd.DataFrame(data = [[1,2],[3,4],[5,6],[7,8],[9,10]],index=[1,2,3,4,5],columns=['a','b']) 
x 
    a b 
1 1 2 
2 3 4 
3 5 6 
4 7 8 
5 9 10 

sollte die Ausgabe

sein
a b 
1 25 30 
2 25 30 
3 25 30 
4 25 30 
5 25 30 

ich x.apply verwenden möchten (f, Achse = 0), aber ich weiß nicht, wie eine Funktion zu definieren, die eine Spalte konvertieren die zu sein Summe aller Spaltenwerte in einer Lambda-Funktion. Die folgende Zeile erhöhen Syntax: kann nicht auf Lambda

f = lambda x : x[:]= x.sum() 
+1

Könnten Sie einen kleinen Ausschnitt aus Ihrem Datenrahmen teilen? –

+1

"Ich kann eine Lambda-Funktion nicht wie folgt definieren": Was lässt dich das sagen? –

+1

Würde 'df.sum()' nicht einfach tun, was Sie wollen - oder wollen Sie * wirklich * alle Spalten mit der Summe überschreiben? (Ich habe Schwierigkeiten, darüber nachzudenken, warum du das machen willst ...) –

Antwort

5

Ein weiterer schneller numpy Lösung mit numpy.tile:

print (pd.DataFrame(np.tile(x.sum().values, (len(x.index),1)), 
        columns=x.columns, 
        index=x.index)) 
    a b 
1 25 30 
2 25 30 
3 25 30 
4 25 30 
5 25 30 

Eine andere Lösung mit numpy.repeat:

h = pd.DataFrame(x.sum().values[np.newaxis,:].repeat(len(x.index), axis=0), 
       columns=x.columns, 
       index=x.index) 

print (h) 
    a b 
1 25 30 
2 25 30 
3 25 30 
4 25 30 
5 25 30 


In [431]: %timeit df = pd.DataFrame([x.sum()] * len(x)) 
1000 loops, best of 3: 786 µs per loop 

In [432]: %timeit (pd.DataFrame(np.tile(x.sum().values, (len(x.index),1)), columns=x.columns, index=x.index)) 
1000 loops, best of 3: 192 µs per loop 

In [460]: %timeit pd.DataFrame(x.sum().values[np.newaxis,:].repeat(len(x.index), axis=0),columns=x.columns, index=x.index) 
The slowest run took 8.65 times longer than the fastest. This could mean that an intermediate result is being cached. 
10000 loops, best of 3: 184 µs per loop 
+0

Dies funktioniert auch mit ziemlich willkürlichen Indizes ... was bedeutet, dass es robust ist, wenn Indizes nicht eindeutig sind. – piRSquared

+0

danke, nur mit meinem Fall 4000+ Zeilen und 2000+ Spalten getestet. Zeitaufwand für drei Methoden sind ungefähr [1.08s, 0.59s, 0.58s] – wh408

0

ordne ich nicht genau wissen, was Sie versuchen zu tun, aber Sie können wie f = lambda x : [column.sum() for column in x]

5
for col in df: 
    df[col] = df[col].sum() 

mit Liste Verständnis, etwas zu tun oder eine langsamere Lösung, die nicht Looping nicht verwendet ...

df = pd.DataFrame([df.sum()] * len(df)) 

Timings

@jezrael Danke für die Zeitplanung. Dies macht sie auf einem größeren Datenrahmen und beinhaltet auch die for-Schleife. Die meiste Zeit verbringen wir die Datenrahmen zu schaffen, statt die Summen berechnen, so die effizienteste Methode, die dieses das von @ayhan sein muss erscheint, der die Summe der Werte zuordnet direkt:

from string import ascii_letters 

df = pd.DataFrame(np.random.randn(10000, 52), columns=list(ascii_letters)) 

# A baseline timing figure to determine sum of each column. 
%timeit df.sum() 
1000 loops, best of 3: 1.47 ms per loop 

# Solution 1 from @Alexander 
%%timeit 
for col in df: 
    df[col] = df[col].sum() 
100 loops, best of 3: 21.3 ms per loop 

# Solution 2 from @Alexander (without `for loop`, but much slower) 
%timeit df2 = pd.DataFrame([df.sum()] * len(df)) 
1 loops, best of 3: 270 ms per loop 

# Solution from @PiRSquared 
%timeit df.stack().groupby(level=1).transform('sum').unstack() 
10 loops, best of 3: 159 ms per loop 

# Solution 1 from @Jezrael 
%timeit (pd.DataFrame(np.tile(df.sum().values, (len(df.index),1)), columns=df.columns, index=df.index)) 
100 loops, best of 3: 2.32 ms per loop 

# Solution 2 from @Jezrael 
%%timeit 
df2 = pd.DataFrame(df.sum().values[np.newaxis,:].repeat(len(df.index), axis=0), 
       columns=df.columns, 
       index=df.index) 
100 loops, best of 3: 2.3 ms per loop 

# Solution from @ayhan 
%time df.values[:] = df.values.sum(0) 
CPU times: user 1.54 ms, sys: 485 µs, total: 2.02 ms 
Wall time: 1.36 ms # <<<< FASTEST 
+0

Danke, gibt es eine Möglichkeit, die for-Schleife zu vermeiden? – wh408

+0

Die for-Schleife ist in diesem Fall vollkommen gültig. – Alexander

+0

ja, aber mein Fall ist, dass ich Tausende von Spalten habe und ich versuche, einen effizienteren Weg zu finden. – wh408

2

mit transform

x.stack().groupby(level=1).transform('sum').unstack() 

enter image description here

+0

danke, nur mit meinem Fall 4000+ Zeilen und 2000+ Spalten getestet. Die Zeit ist ungefähr 10s – wh408

4

Wenn Ihr Datenrahmen von Zahlen besteht, können Sie direkt ihre Werte ändern:

df.values[:] = df.sum() 
+0

Das ist sehr schnell! – piRSquared

+2

Besser noch 'df.values ​​[:] = df.values.sum (0)' – piRSquared

+0

Ja, es scheint der bisher schnellste zu sein, obwohl es schwer zu testen ist, da die Werte sehr schnell gegen unendlich konvergieren, fürchte ich könnte die Timings beeinflussen. – ayhan

Verwandte Themen