2015-12-21 74 views
2

必須有一個簡單的方法來做到這一點,但我錯過了它。首先,想象在Excel中的情況:高效的做熊貓操作和跳行的方式

  1. 我有一列百分比變化。 (假設列A)
  2. 在下一列(B)中,我想根據百分比變化創建一個以1000開始的索引系列。在Excel中,我是這樣做的。 -set B1 to 1000 -set B2 to formula =(1 + A2)* B1 - 將列拷貝下來。簡單。

現在,我想做與大熊貓同樣的事情,問題是目標數組在下面的代碼結果成爲楠:

import pandas as pd 
import numpy as np 

df_source = pd.DataFrame(np.random.normal(0,.05,10), index=range(10), columns=['A']) 

df_target = pd.DataFrame(index = df_source.index) 
df_target.loc[0,"A"] = 1000 # initialize target array to start at 1000 

df_target["A"] = (1 + df_source) * df_target["A"].shift(1) # How to skip first row? 

目標陣列變成NaN,因爲第一行試圖引用「關閉數據框」的值,所以整列返回NaN。

我意識到我可以用循環遍歷行,跳過第一行,但是這對於數據集或迭代的大小來說是非常緩慢和不實際的。

必須有一種方法來使用熊貓/ numpy數組函數,但要告訴它跳過計算中的第一行。怎麼做?我試過布爾編制索引,但不能讓它起作用,也許有辦法告訴熊貓跳過NaN結果......但最好的方法似乎是一個限定詞,說「應用此代碼,從第二排「。

我在這裏錯過了什麼?

編輯:

看起來像我的問題比我意識到更深。 jezrael的答案解決了NA問題,但我認爲我對熊貓邏輯感到困惑。我上面給出的代碼不工作,因爲它不工作元素。例如,簡單的例子:

seriesdf = pd.DataFrame(index = range(10)) 
seriesdf['A'] = 1 
seriesdf['A'].ix[1:] = 1 + seriesdf['A'].shift(1) 

給出結果

A 
0 1 
1 2 
2 2 
3 2 
4 2 
5 2 
6 2 
7 2 
8 2 
9 2 

沒有上升計數爲我承擔了。所以問題是在熊貓數據框上逐行計算的最有效方法是什麼?速度在這個應用程序很重要,所以我寧願不通過行。

新的Python程序員在這裏試圖弄清楚這一點。這些答案向我展示瞭如何學習/爲自己繪製這樣的東西,非常感謝。謝謝!

+0

嗯,你想要的輸出是什麼?最好的東西是[在這裏](http://pandas.pydata.org/pandas-docs/stable/10min.html)。 – jezrael

+0

感謝您對此@jezrael的幫助。這些解決方案的工作,但熊貓.cumprod()原來是最簡單的解決方案。考慮到python與速度更快的語言的速度非常關鍵,以避免在可能的情況下迭代。謝謝! – mmee

+0

超級,它的工作。我認爲'熊貓'是一個了不起的圖書館。 – jezrael

回答

0

IIUC您可以選擇通過ix跳過df_sourceA列的第一行,而不首先行:

df_target["A"].ix[1:] = df_source['A'].ix[1:] + 1 
print df_target 
      A 
0 1000.000000 
1  0.988898 
2  0.986142 
3  1.009979 
4  1.005165 
5  1.101116 
6  0.992312 
7  0.962890 
8  1.051340 
9  1.009750 

或者,也許你認爲:

import pandas as pd 
import numpy as np 

df_source = pd.DataFrame(np.random.normal(0,.05,10), index=range(10), columns=['A']) 
print df_source 
      A 
0 0.039965 
1 0.060821 
2 -0.079238 
3 -0.129932 
4 0.002196 
5 -0.003721 
6 -0.008358 
7 0.014104 
8 -0.022905 
9 0.014793 

df_target = pd.DataFrame(index = df_source.index) 
#all A set to 1000 
df_target["A"] = 1000 # initialize target array to start at 1000 
print df_target 
     A 
0 1000 
1 1000 
2 1000 
3 1000 
4 1000 
5 1000 
6 1000 
7 1000 
8 1000 
9 1000 
df_target["A"] = (1 + df_source["A"].shift(-1))* df_target["A"] 
print df_target 
      A 
0 1060.820882 
1 920.761946 
2 870.067878 
3 1002.195555 
4 996.279287 
5 991.641909 
6 1014.104402 
7 977.094961 
8 1014.793488 
9   NaN 

編輯:

也許你需要cumsum

df_target["B"] = 2 
df_target["C"] = df_target["B"].cumsum() 

df_target["D"] = df_target["B"] + df_target.index 
print df_target 
      A B C D 
0 1041.003000 2 2 2 
1 1013.817000 2 4 3 
2 948.853000 2 6 4 
3 1031.692000 2 8 5 
4 970.875000 2 10 6 
5 1011.095000 2 12 7 
6 1053.472000 2 14 8 
7 903.765000 2 16 9 
8 1010.546000 2 18 10 
9  0.010546 2 20 11 
+0

如果我的回答很有幫助,你可以[接受](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work)它。 – jezrael

+0

我忘了 - 歡迎來到'pandas'和'StackOverflow'。你可以檢查[tour](http://stackoverflow.com/tour)。 – jezrael

0

我想我明白你的問題,在這種情況下,我通常會發現很容易使一個列表並將它添加到現有的數據幀。當然,您可以先製作一個Series實例,然後,然後做計算。建立大熊貓贊成ix

new_series = [0]*len(df["A"])     
new_series[0] = 1000       

for i,k in enumerate(dataframe["A"].ix[1:]): 
    new_series[i] = (1 + k)*new_series[i-1]  

dataframe["B"] = pd.Series(new_series)   

IIRC,ILOC正在將來棄用重新思考這個問題後,您可以使用lambda表達式作爲元素在你的數據幀

dataframe["B"] = [lambda row: (1 + dataframe["A"].ix[row])*dataframe["B"].ix[row-1]*len(dataframe["A"]) 
# Above: initiate "B" with a lambda expression that is as long as "A" 

dataframe["B"].ix[0] = 1000 
for i,k in enumerate(dataframe["B"].ix[1]): 
    dataframe["B"].ix[i] = k(row=i) 

我想嘗試使用for循環來解決這個問題,但不能管理e來確定從哪裏獲取行號。

希望這會有所幫助。

+0

感謝您對此提供的幫助以及關於iloc的注意事項。 – mmee