2014-05-05 61 views
4

我想添加一列到df。這個新的df的值將取決於其他列的值。例如python熊貓數據框如果沒有迭代思想數據框

dc = {'A':[0,9,4,5],'B':[6,0,10,12],'C':[1,3,15,18]} 
df = pd.DataFrame(dc) 
    A B C 
0 0 6 1 
1 9 0 3 
2 4 10 15 
3 5 12 18 

現在我想添加另一列D,其值取決於A,B,C的值。 因此,例如,如果是通過DF我只想做迭代:

for row in df.iterrows(): 
    if(row['A'] != 0 and row[B] !=0): 
     row['D'] = (float(row['A'])/float(row['B']))*row['C'] 
    elif(row['C'] ==0 and row['A'] != 0 and row[B] ==0): 
     row['D'] == 250.0 
    else: 
     row['D'] == 20.0 

有沒有辦法做到這一點沒有for循環或使用其中()或適用()函數。

感謝

回答

2

這裏是一個開始:

df['D'] = np.nan 
df['D'].loc[df[(df.A != 0) & (df.B != 0)].index] = df.A/df.B.astype(np.float) * df.C 

編輯,你應該先走一步,投整件事浮動,除非你真的在乎出於某種原因整數:

df = df.astype(np.float) 

然後你不必經常保持轉換通話本身

5

apply應該爲你工作得好:

In [20]: def func(row): 
      if (row == 0).all(): 
       return 250.0 
      elif (row[['A', 'B']] != 0).all(): 
       return (float(row['A'])/row['B']) * row['C'] 
      else: 
       return 20 
     ....:  


In [21]: df['D'] = df.apply(func, axis=1) 

In [22]: df 
Out[22]: 
    A B C  D 
0 0 6 1 20.0 
1 9 0 3 20.0 
2 4 10 15 6.0 
3 5 12 18 7.5 

[4 rows x 4 columns] 
+0

非常感謝!也會像這樣的工作。 ('['','B']]!= 0和行['C']!= None).all(): 我必須檢查無條件以及 – cryp

+0

你可能應該將這些'None'轉換爲'NaN's。你會得到更好的性能,因爲它將是一個float dtype而不是column,並且pandas操作是NaN知道的。 – TomAugspurger

+0

哦,好的,謝謝!所以這樣的事情? elif(row [['A','B']]!= 0 and row ['C']!= NaN).all() – cryp

2

.where可以比.apply快得多,所以,如果你正在做的是,如果/別人的話,我會瞄準.where。當你在某些情況下返回標量時,np.where比熊貓自己的.where更容易使用。

import pandas as pd 
import numpy as np 
df['D'] = np.where((df.A!=0) & (df.B!=0), ((df.A/df.B)*df.C), 
      np.where((df.C==0) & (df.A!=0) & (df.B==0), 250, 
      20)) 

    A B C  D 
0 0 6 1 20.0 
1 9 0 3 20.0 
2 4 10 15 6.0 
3 5 12 18 7.5 

對於這樣一個微小的df,你不需要擔心速度。但是,在randn的10000行df上,這比上面的解決方案.apply快了近2000倍:3ms vs 5850ms。這就是說,如果速度不是問題,那麼應用程序通常可以更容易閱讀。