2015-11-20 50 views
1

如何根據來自其他列的值同時添加幾個新列?我只找到了一次添加一行的示例。panda基於來自其他列的值同時添加幾個新列?

我可以添加3個新列,但這看起來並不高效,因爲它必須遍歷所有行3次。 有沒有辦法穿越DF一次?

import pandas as pd 
from decimal import Decimal 
d = [ 
    {'A': 2, 'B': Decimal('628.00')}, 
    {'A': 1, 'B': Decimal('383.00')}, 
    {'A': 3, 'B': Decimal('651.00')}, 
    {'A': 2, 'B': Decimal('575.00')}, 
    {'A': 4, 'B': Decimal('1114.00')}, 
] 

df = pd.DataFrame(d) 

In : df 
Out: 
    A  B 
0 2 628.00 
1 1 383.00 
2 3 651.00 
3 2 575.00 
4 4 1114.00 

# How to do those in one operation to avoid traversing the DF 3 times 
df['C'] = df.apply(lambda row: row['B']-1000, axis=1) 
df['D'] = df.apply(lambda row: row['B']*row['B'], axis=1) 
df['E'] = df.apply(lambda row: row['B']/2, axis=1) 

In : df 
Out: 
    A  B  C    D  E 
0 2 628.00 -372.00 394384.0000 314.00 
1 1 383.00 -617.00 146689.0000 191.50 
2 3 651.00 -349.00 423801.0000 325.50 
3 2 575.00 -425.00 330625.0000 287.50 
4 4 1114.00 114.00 1240996.0000 557.00 

回答

1

我不會使用lambda函數。簡單的矢量化實現既快又易於閱讀。

df['C'] = df['B'] - 1000 
df['D'] = df['B'] ** 2 
df['E'] = df['B']/2 

>>> df 
    A  B  C    D  E 
0 2 628.00 -372.00 394384.0000 314.00 
1 1 383.00 -617.00 146689.0000 191.50 
2 3 651.00 -349.00 423801.0000 325.50 
3 2 575.00 -425.00 330625.0000 287.50 
4 4 1114.00 114.00 1240996.0000 557.00 

讓我們一次對數據幀一個百萬行:

df = pd.concat([df for _ in range(200000)], ignore_index=True) 
>>> df.shape 
(1000000, 2) 

>>> %%timeit -n 3 
    df['C'] = df.apply(lambda row: row['B'] - 1000, axis=1) 
    df['D'] = df.apply(lambda row: row['B'] * row['B'], axis=1) 
    df['E'] = df.apply(lambda row: row['B']/2, axis=1) 
3 loops, best of 3: 1min 20s per loop 

>>> %%timeit -n 3 
    df['C'] = df['B'] - 1000 
    df['D'] = df['B'] ** 2 
    df['E'] = df['B']/2 
3 loops, best of 3: 49.7 s per loop 

速度是顯著更快如果廢除了十進制類型和使用的浮動改爲:

d = [ 
    {'A': 2, 'B': 628.00}, 
    {'A': 1, 'B': 383.00}, 
    {'A': 3, 'B': 651.00}, 
    {'A': 2, 'B': 575.00}, 
    {'A': 4, 'B': 1114.00}] 

df = pd.DataFrame(d) 
df = pd.concat([df for _ in range(200000)], ignore_index=True) 

>>> %%timeit -n 3 
    df['C'] = df['B'] - 1000 
    df['D'] = df['B'] ** 2 
    df['E'] = df['B']/2 
3 loops, best of 3: 33.1 ms per loop 

>>> df.shape 
(1000000, 5) 
+0

此操作的速度是否重要尚不得而知 - 它可能根本就不是。不過,使用串行操作確實是一種很好的,正常的,可讀的事情,而不適用於這種情況。 –

+0

@MikeGraham鑑於OP在第二段關於效率的評論,我將其解釋爲速度效率。 – Alexander

+0

很好的回答。謝謝。如果我非常瞭解大熊貓的工作原理,那麼每次我們添加的每一行/新列都必須通過整個DF?所以在這種情況下,它會在整個DF中循環3次,因爲我們添加了3列。如果我想添加更多的列,是否有一種方法可以改善這種情況,因爲每次都沒有經過整個DF的時間。是否有可能同時計算每行上的所有新列,並因此只循環一次DF?反正它可能不快?我還不太瞭解熊貓。謝謝。 – Michael