2017-10-31 17 views
1

最も早い開始日と最新の終了日を取得するために、パンダのcsvファイル(1列:ID)でグループ化しようとしています。次に、値のSUMを得るために複数の列でグループ化しようとしています。 2番目のgroupedbyデータフレームの各IDについて、日付を提示したい。Pandasグループ、2つの列を集めて1つの列の最も早い開始日を返します

データをグループ化して集約するためにcsvをロードしています。期待と私として働い

01)まず私はIDとサイト(CSV

def get_csv(): 
     #Read csv file 
     df = pd.read_csv('myFile.csv', encoding = "ISO-8859-1",parse_dates=['Start Date', 'End Date']) 

     return df 

02)グループをロードし、列のデータを集計)

def do_stuff(): 
    df = get_csv() 
    groupedBy = df[df['A or B'].str.contains('AAAA')].groupby([df['ID'], df['Site'].fillna('Other'),]).agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum'}) 

次のようになります(例):

enter image description here

03)また、同じIDの場合、開始日の列に最も早い日付を、終了日の列に最新の日付を表示することが理想的です。値の集計は完全に機能します。私は上記の私の現在のコードを変更する方法がわからない

enter image description here

:私は何を取得したいことは以下の通りです。私はこれまでのところ、これを試してみました:ともに上記の変更を試みたが失敗

def do_stuff(): 
    df = get_csv() 
    md = get_csv() 

    minStart = md[md['A or B'].str.contains('AAAA')].groupby([md['ID']]).agg({'Start Date': 'min'}) 

    df['earliestStartDate'] = minStart 

    groupedBy = df[df['A or B'].str.contains('AAAA')].groupby([df['ID'], df['Site'].fillna('Other'),df['earliestStartDate']]).agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum'}) 

:理想的には

def do_stuff(): 
    df = get_csv() 
    md = get_csv() 

    df['earliestStartDate'] = md.loc[ md['ID'] == df['ID'], 'Start Date'].min() 

    groupedBy = df[df['A or B'].str.contains('AAAA')].groupby([df['ID'], df['Site'].fillna('Other'),df['earliestStartDate']]).agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum'}) 

が、私はだけではなく、二回csvファイルを読むために持つのgroupedByで何かを変更し、データを2回集約する。それは可能ですか?そうでない場合は、スクリプトを動作させるために何を変更できますか?私はPandasとPythonでより多くの経験を得るためにランダムなものをテストしようとしています。

私はここに2つのdataframesを作成する必要があると推測しています。 1つは、必要なすべての列(および値のSUM)のデータをgroupedbyに取得することです。各IDの最も早い開始日と最新の終了日を取得するもう1つのIDです。次に、2つを連結する方法を見つける必要がありますdataframes。それは良い結果ですか、それを達成するためのより簡単な方法があると思いますか?

UPD:私は2つのデータフレーム(これは適切なソリューションであるかどうかわからないが)作成している私のコードは以下の通りである:

#Read csv file 
df = pd.read_csv('myFile.csv', encoding = "ISO-8859-1",mangle_dupe_cols=True, parse_dates=['Start Date', 'End Date']) 
md = pd.read_csv('myFile.csv', encoding = "ISO-8859-1",mangle_dupe_cols=True, parse_dates=['Start Date', 'End Date']) 


#Calculate the Clean Value 
df['Clean Cost'] = (df['Value'] - df['Value2']) #.apply(lambda x: round(x,0)) 

#Get the min/max Dates 
minMaxDates = md[md['Random'].str.contains('Y')].groupby([md['ID']]).agg({'Start Date': 'min', 'End Date': 'max'}) 

#Group by and aggregate (return Earliest Start Date, Latest End Date and SUM of the Values) 
groupedBy = df[df['Random'].str.contains('Y')].groupby([df['ID'], df['Site'].fillna('Other')]).agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum', 'Value2': 'sum', 'Clean Cost': 'sum'}) 

と私は2つのデータフレームを印刷する場合、私は次のように取得しています:

minMaxDates

enter image description here

dfを印刷すると

ID A or B Start Date End Date Value Site Value2 Random             alse. 

0 45221 AAAA 2017年12月30日2017年9月30日14 S111 7 Y 1 45221 AAAA 2017年1月15日2017年9月30日:頭()、私は次のように取得しています15 S222 7 Y 2 85293 BBBB 2017-05-12 2017-07-24 29 S111 3 Y 3 85293 AAAA 2017-03-22 2017-10-14 32 S222 4 Y 4 45221 AAAA 2017-01-15 2017 -09-30 30 S222 7 Yは

ファイルのリンクをここに与えられます。LINK

+2

あなたはあなたのコードを複製するのに十分な、小さなサンプルデータフレームを提供することはできますか? – ASGM

+0

@ASGM私はgroupedbyとminMaxDatesを印刷しました。私は質問を更新しました。それで十分ですか? –

+0

イメージではなくコードとして提供できますか?投稿したコードをコピーして貼り付け、問題を再現して解決策を見つけることができれば、有益な答えを得る可能性は非常に高いです。 – ASGM

答えて

2

は、私はあなたがtransformが必要だと思う:

df = pd.read_csv('sampleBionic.csv') 
print (df) 
     ID A or B Start Date End Date Value Site Value2 Random 
0 45221 AAAA 12/30/2017 09/30/2017  14 S111  7  Y 
1 45221 AAAA 01/15/2017 09/30/2017  15 S222  7  Y 
2 85293 BBBB 05/12/2017 07/24/2017  29 S111  3  Y 
3 85293 AAAA 03/22/2017 10/14/2017  32 S222  4  Y 
4 45221 AAAA 01/15/2017 09/30/2017  30 S222  7  Y 

groupedBy = (df[df['A or B'].str.contains('AAAA')] 
          .groupby([df['ID'], df['Site'].fillna('Other'),]) 
          .agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum'})) 
print (groupedBy)  
      Start Date End Date Value 
ID Site        
45221 S111 12/30/2017 09/30/2017  14 
     S222 01/15/2017 09/30/2017  45 
85293 S222 03/22/2017 10/14/2017  32 

g = groupedBy.groupby(level=0)    
groupedBy['Start Date'] = g['Start Date'].transform('min') 
groupedBy['End Date'] = g['End Date'].transform('max') 
print (groupedBy) 
      Start Date End Date Value 
ID Site        
45221 S111 01/15/2017 09/30/2017  14 
     S222 01/15/2017 09/30/2017  45 
85293 S222 03/22/2017 10/14/2017  32 
+0

それはうまく動作します:)あなたのスクリプトは私よりも少ない行を持っています。 –

+0

ようこそ。残念ながら、 'transform'は' agg'のような 'dictionary'では動作しませんので、2行必要です。いい日! – jezrael

0

私は私が欲しいものを行うスクリプトを作成するために管理しています。私は誰かが将来必要とする場合に備えて答えを貼り付けます。イズラエルの答えもうまくいった。だから、元のCSVは次のようにあることを考慮: enter image description here

私sriptは次のとおりです。

import pandas as pd 
import os 
import csv 
import time 
import dateutil.parser as dparser 
import datetime 


def get_csv(): 
     #Read csv file 
     df = pd.read_csv('myFile.csv', encoding = "ISO-8859-1",mangle_dupe_cols=True, parse_dates=['Start Date', 'End Date']) 
     df = df[df['A or B'].str.contains('AAAA')] 

     return df 

def do_stuff(): 
    df = get_csv() 

    #Get the min Start Date, max End date, sum of the Value and Value2 and calculate the Net Cost 
    varA  = 'ID'; 
    dfGrouped = df.groupby(varA, as_index=False).agg({'Start Date': 'min', 'End Date': 'max'}).copy(); 

    varsToKeep = ['ID', 'Site', 'Random', 'Start Date_grp', 'End Date_grp', 'Value', 'Value2', ]; 
    dfTemp = pd.merge(df, dfGrouped, how='inner', on='ID', suffixes=(' ', '_grp'), copy=True)[varsToKeep]; 

    dfBreakDown = dfTemp.groupby(['ID', 'Site', 'Random', 'Start Date_grp', 
     'End Date_grp']).sum() 

    #Calculate the Net Cost 
    dfTemp['Net Cost'] = (dfTemp['Value'] - dfTemp['Value2']) 

    groupedBy = dfTemp.groupby(['ID', 'Site', 'Random']).agg({'Start Date_grp': 'min', 'End Date_grp': 'max', 'Value': 'sum', 'Value2': 'sum', 'Net Cost': 'sum'}) 

    csvoutput(groupedBy) 

def csvoutput(df): 
     #Csv output 
     df.to_csv(path_or_buf='OUT.csv', sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression=None, quoting=None, quotechar='"', line_terminator='\n', chunksize=None, tupleize_cols=False, date_format=None, doublequote=True, escapechar=None, decimal='.') 

if __name__ == "__main__": 
     # start things here 
     do_stuff() 
関連する問題