2017-09-27 11 views
0

別のテーブルの値(およびcountif)に基づいて2Dテーブルを作成したいと思います。私は、しかし、私は二つの概念で立ち往生しています、これが正常にExcelを使用してプロトタイプを作成するために管理:パンダを使用して別のExcelシートのCOUNTIF()に基づく2Dテーブルを作成する

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

注:COUNTIF()の範囲および引数として基準をとります。例えば、私は色のリストを持っていると私は時代「オレンジ」の数は、以下のリストにあるお知りになりたい場合:

COUNTIF(A1:A5, "Orange") 

A 
Red 
Orange 
Blue 
Orange 
Black 

、その後、私は単純に次の式を使用します

これは、(範囲1、条件1、Range2の、条件2は、...)として解釈することができ、このフォームCOUNTIFで条件を連結する形態例として、コースCOUNTIF 2.

()関数がより複雑になる可能性が返さなければなりません批評家。私は以下のようなリストでは35以上の女性の数をwantto場合例:

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 

そして、これは私が達成したい2D行列である:基本的に私は時間を通じて、製品の生存のマトリックスを構築したい

  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 

。縦軸は新製品の生産を保有していますが、横軸はこれらの勘定のどれくらいが時間を通じて持続するかを測定します。

たとえば、1月に10製品が発売された場合、1月と1月の数字は10になります。これらの10製品のうち1製品が2月に閉鎖された場合、1月と2月は9となります。 1月と6月、7月、8月などの行は0でなければなりません。

2月、3月、4月などの製品開発は1月の行には影響しません。

私は、次の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-loopsの数を入力することができますが、私はPandasにもっと簡単な方法(または推奨方法)があるかどうかはわかりません。

答えて

1

私はまだあなたの質問にコメントするのに十分な評判を持っていないので、私は」あなたのデータに年が2099年であるタイプミスがあると仮定します。

あなたの2016年06月30日の行には、何らかの形で最初の数行(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() 

第三に、私はわずかにDATERANGEと一緒に元のDF及びリミット行とき「製品番号」を含むマージ存在した。また、閉鎖された日付は、その月の最終日に製品が閉鎖された場合(私の意見では)閉鎖された日付が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')) 
関連する問題