2017-09-27 29 views
0

我想建立基於從另一表中的值(和COUNTIFS)二維表()的基礎上COUNTIF二維表。我管理這個成功使用Excel爲原型,但我堅持兩個概念:使用大熊貓建立「一個單獨的第Excel表單

1. Emulating Excel COUNTIF() on pandas 
2. Dynamically build a new dataframe 

注:COUNTIF()需要一個範圍和標準作爲參數。例如,如果我有一個顏色列表,我想知道的時候「橙」的數量是在下面的列表:

A 
Red 
Orange 
Blue 
Orange 
Black 

,那麼我會簡單地使用下面的公式:

COUNTIF(A1:A5, "Orange") 

這應返回2.

當然COUNTIF()的功能可以如形式示例變得更加複雜,在這種形式COUNTIF級聯標準(範圍1,條件1,範圍2 2,條件2 ...)可以被解釋爲一個與criterian。例如,如果我在一個列表wantto女性的數量超過35個類似下面:

A    B 
Female  19 
Female  40 
Male   45 

,那麼我會簡單地使用下面的公式:

COUNTIF(A1:A3, "Female", B1:B3, ">35" 

這應返回1.

回到我的用例。這是源表:

Product No Opening Date Closing Date Opening Month Closing Month 
0   1 2016-01-01 2016-06-30 2016-01-31 2016-06-30 
1   2 2016-01-01 2016-04-30 2016-01-31 2016-04-30 
2   3 2016-02-01 2016-06-30 2016-02-29 2016-06-30 
3   4 2016-02-01 2016-05-31 2016-02-29 2016-05-31 
4   5 2016-02-01 2099-12-31 2016-02-29 2099-12-31 
5   6 2016-01-01 2099-12-31 2016-01-31 2016-10-31 
6   7 2016-06-01 2016-07-31 2016-06-30 2016-07-31 
7   8 2016-06-01 2016-11-30 2016-06-30 2016-11-30 
8   9 2016-06-01 2016-07-31 2016-06-30 2016-07-31 
9   10 2016-06-01 2099-12-31 2016-06-30 2099-12-31 

這是我想要達到的二維矩陣:

  2016-01-31 2016-02-29 2016-03-31 2016-04-30 2016-05-31 \ 
2016-01-31   3   3   3   2   2 
2016-02-29   3   3   3   3   2 
2016-03-31   0   0   0   0   0 
2016-04-30   0   0   0   0   0 
2016-05-31   0   0   0   0   0 
2016-06-30   4   4   4   4   4 
2016-07-31   0   0   0   0   0 
2016-08-31   0   0   0   0   0 
2016-09-30   0   0   0   0   0 
2016-10-31   0   0   0   0   0 
2016-11-30   0   0   0   0   0 
2016-12-31   0   0   0   0   0 

      2016-06-30 2016-07-31 2016-08-31 2016-09-30 2016-10-31 \ 
2016-01-31   1   1   1   1   0 
2016-02-29   1   1   1   1   1 
2016-03-31   0   0   0   0   0 
2016-04-30   0   0   0   0   0 
2016-05-31   0   0   0   0   0 
2016-06-30   4   2   2   2   2 
2016-07-31   0   0   0   0   0 
2016-08-31   0   0   0   0   0 
2016-09-30   0   0   0   0   0 
2016-10-31   0   0   0   0   0 
2016-11-30   0   0   0   0   0 
2016-12-31   0   0   0   0   0 

      2016-11-30 2016-12-31 
2016-01-31   0   0 
2016-02-29   1   1 
2016-03-31   0   0 
2016-04-30   0   0 
2016-05-31   0   0 
2016-06-30   1   1 
2016-07-31   0   0 
2016-08-31   0   0 
2016-09-30   0   0 
2016-10-31   0   0 
2016-11-30   0   0 
2016-12-31   0   0 

基本上,我想通過時間來建立產品生存的矩陣。縱軸表示新產品的起源,而橫軸表示這些帳戶在多長時間內持續存在。

例如,如果10個產品是在1月推出,這個數字對於一月VS月份應該是10.如果這10種產品的1〜2月被關閉,這個數字對於一月二月VS應該9.如果所有剩餘產品在六月被關閉,那麼行一月VS六月,七月,八月,等應該是在二月,三月,四月0

產品開發等。不會影響到一月一行。

我管理使用以下Excel公式來構建2D矩陣:

=COUNTIF(Accounts!$D$2:$D$11,Main!$A2)-COUNTIFS(Accounts!$D$2:$D$11,Main!$A2, Accounts!$E$2:$E$11,"<="&Main!B$1) 

(這將填充所述第一小區)

我最初的策略是建立一個多維列表,並使用數for循環來填充他們,但我不知道是否有一個更簡單(或更多建議的方式)在熊貓。

回答

1

因爲我沒有足夠的聲譽對您的問題發表評論,只是還沒有,我我會假設你在你的數據中有年份等於2099的錯別字。

我還想問你在2016-06-30行如何有4個'產品號'在某種程度上存在於前幾列(即2016-01-31至2016-05-31)。

如果那些錯誤,那麼這裏是我的解決方案:

首先,使數據:

# Make dataframe 
df = pd.DataFrame({'Product No' : [i for i in range(1,11)], 
        'Opening Date' : ['2016-01-01']*2 +\ 
            ['2016-02-01']*3 +\ 
            ['2016-01-01'] +\ 
            ['2016-06-01']*4, 
        'Closing Date' : ['2016-06-30', '2016-04-30', '2016-06-30', '2016-05-31'] +\ 
            ['2016-12-31']*2 +\ 
            ['2016-07-31', '2016-11-30', '2016-07-31', '2016-12-31'], 
        'Opening Month' : ['2016-01-31']*2 +\ 
            ['2016-02-29']*3 +\ 
            ['2016-01-31'] +\ 
            ['2016-06-30']*4, 
        'Closing Month' : ['2016-06-30', '2016-04-30', '2016-06-30', '2016-05-31', 
             '2016-12-31', '2016-10-31', '2016-07-31', '2016-11-30', 
             '2016-07-31', '2016-12-31']}) 

# Reorder columns 
df = df.loc[:, ['Product No', 'Opening Date', 'Closing Date', 
       'Opening Month', 'Closing Month']] 

# Convert dates to datetime 
for i in df.columns[1:]: 
    df.loc[:, i] = pd.to_datetime(df.loc[:, i]) 

其次,我創建了一個「日期範圍」數據框用於保持分鐘到原來的最大日期數據集。我還包括一個「產品編號」一欄,使每個產品都會對錶中的一行:

# Create date range dataframe 
daterange = pd.DataFrame({'daterange' : pd.date_range(start = df.loc[:, 'Opening Month'].min(), 
                end = df.loc[:, 'Closing Month'].max(), 
                freq = 'M'), 
          'Product No' : [1]*12}) 

# Create 10 multiples of the daterange and concatenate 
daterange10 = pd.concat([daterange]*10) 

# Find the cumulative sum of the 'Product No' for daterange10 
daterange10.loc[:, 'Product No'] = daterange10.groupby('daterange').cumsum() 

第三,我合併的日期範圍和原來的DF在一起,並限制行僅包括當一個「產品編號」存在。另外請注意,如果產品在本月的最後一天關閉,那麼關閉日期必須大於或等於自(以我的觀點)以來的日期範圍,然後在整個月中存在:

# Merge df with daterange10 
df = df.merge(daterange10, 
       how = 'inner', 
       on = 'Product No') 

# Limit rows to when 'Opening Month' is <= 'daterange' and 'Closing Month' is >= 'daterange' 
df = df[(df.loc[:, 'Opening Month'] <= df.loc[:, 'daterange']) & 
     (df.loc[:, 'Closing Month'] >= df.loc[:, 'daterange'])] 

最後,我用日期值做一個數據透視表。請注意,它僅包括對在首位存在的縱軸日期:

# Pivot on 'Opening Month', 'daterange'; count unique 'Product No'; fill NA with 0 
df.pivot_table(index = 'Opening Month', 
       columns = 'daterange', 
       values = 'Product No', 
       aggfunc = pd.Series.nunique).fillna(0) 

pivot_table

+0

非常理解,我設法學習一些技巧的。謝謝! –

0

嘗試把你的數據轉換成數據幀的大熊貓,然後使用迭代方法來構建產品的生存數據框:

import pandas as pd 

mydata = pd.read_excel('mysourcedata.xlsx') 

def product_survival(sourcedf, startdate, enddate): 

    df = pd.DataFrame() 

    daterange = pd.date_range(startdate, enddate, freq='M') 

    for i in daterange: # Rows 
     for j in daterange: # Columns 
      mycount = sourcedf[(sourcedf['Opening Month'] == i) & (sourcedf['Closing Month'] > j)]['Product No'].count() 
      df.loc[i, j] = mycount 

    return df 

print(product_survival(mydata, '2016-01-31', '2016-12-31')) 
相關問題