質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

3回答

2152閲覧

作業時間と件数を日毎に集計したい

luria

総合スコア1

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2021/09/20 02:51

編集2021/09/20 04:58

前提・実現したいこと

以下のCSVがあるとします。

person,date,work A,2021/9/20 8:00,10 A,2021/9/20 10:00,20 A,2021/9/20 18:00,30 B,2021/9/19 9:00,15 B,2021/9/19 20:00,25 C,2021/9/20 10:00,5 C,2021/9/20 15:00,40 C,2021/9/20 19:00,35

これを、日ごと、personごとに作業時間とworkの合計を出したいです。
期待する結果は以下です

person,date,worktime,work_sum A,2021/9/20,10:00,60 B,2021/9/19,11:00,40 C,2021/9/20,09:00,80

試したこと

日毎のworkの合計は出せましたが、作業時間の出し方が難しく、実現できていません。

python

1import pandas as pd 2df = pd.read_csv('sample.csv',parse_dates=[1],index_col=1 ) 3df.groupby('person').resample('D').agg('sum')
person date work A 2021-09-20 60 B 2021-09-19 40 C 2021-09-20 80

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2021/09/20 04:19

そのworktimeってのはcsvからどうやって算出されるもんなんでしょうか
luria

2021/09/20 04:58

質問ありがとうございます。 その日の一番早い時刻から一番遅い時刻までの時間になります。 Aの9/20は8:00〜18:00になるので10時間、となります。 ・・と改めて見るとCの結果が間違っていました。。修正します。
guest

回答3

0

解決済みですが、pandas.Grouperを使えば、日ごとの集計がgroupbyでできるので、もう少し簡単に書けます。

workは合計、dateは最大と最小を集計してその差を整形します。

python

1import pandas as pd 2 3df = pd.read_csv('sample.csv', parse_dates=['date']) 4 5df2 = df.groupby( 6 ['person', pd.Grouper(key='date', freq='D')] 7).agg( 8 worktime0=('date', 'min'), 9 worktime1=('date', 'max'), 10 worksum=('work', 'sum') 11) 12 13df2['worktime'] = (df2['worktime1'] - df2['worktime0']).map( 14 lambda d: '{0.hours}:{0.minutes:02}'.format(d.components)) 15 16df2[['worktime', 'worksum']].to_csv('output.csv', date_format='%Y/%m/%d')

投稿2021/09/20 11:15

bsdfan

総合スコア4794

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

同一personの複数のdateの情報の集計に対応できていなかったため修正しておきます。
'sample.csv' は ppaul さんご提示の内容の前提です。

Python

1import pandas as pd 2import datetime 3 4df = pd.read_csv('sample.csv', parse_dates=[1], index_col=1) 5df2 = df.groupby('person').resample('D').agg('sum') 6df = df.reset_index() 7df2 = df2.reset_index() 8df['name_date'] = df['person']+df['date'].dt.strftime('%Y/%m/%d') 9df2['name_date'] = df2['person']+df2['date'].dt.strftime('%Y/%m/%d') 10df_lst = [df[df['name_date'] == nd] for nd in df2['name_date'].values] 11df2['worktime'] = [df['date'].values[-1] - df['date'].values[0] for df in df_lst] 12df2['worktime'] = df2['worktime'].apply(lambda x: (datetime.datetime(1,1,1)+x).time()) 13df2 = df2.rename(columns={'work': 'work_sum'}) 14df2 = df2.reindex(columns=['person', 'date', 'worktime', 'work_sum']) 15print(df2) 16""" 17 person date worktime work_sum 180 A 2021-09-20 10:00:00 60 191 B 2021-09-19 11:00:00 40 202 C 2021-09-19 08:00:00 80 213 C 2021-09-20 09:00:00 80 22"""

以下、修正前のコードです。

Python

1import pandas as pd 2import datetime 3 4df = pd.read_csv('sample.csv', parse_dates=[1], index_col=1) 5df2 = df.groupby('person').resample('D').agg('sum') 6df = df.reset_index() 7df2 = df2.reset_index() 8df_n = [df[df['person'] == name] for name in df2['person'].values] 9df2['worktime'] = [df['date'].values[-1] - df['date'].values[0] for df in df_n] 10df2['worktime'] = df2['worktime'].apply(lambda x: (datetime.datetime(1,1,1)+x).time()) 11df2 = df2.rename(columns={'work': 'work_sum'}) 12df2 = df2.reindex(columns=['person', 'date', 'worktime', 'work_sum']) 13print(df2) 14""" 15 person date worktime work_sum 160 A 2021-09-20 10:00:00 60 171 B 2021-09-19 11:00:00 40 182 C 2021-09-20 09:00:00 80 19"""

投稿2021/09/20 05:26

編集2021/09/20 09:45
lehshell

総合スコア1156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

luria

2021/09/20 10:02

早い回答大変助かりました。コードの方も知らないテクニックばかりで参考になりました。 ありがとうございました!
guest

0

ベストアンサー

こういう感じです。

python

1df = pd.read_csv('sample.csv',parse_dates=[1]) 2print(df) 3df['date_str'] = df['date'].dt.strftime('%Y/%m/%d') 4sr_worktime = (df.groupby(['person', 'date_str'])['date'].max() - df.groupby(['person', 'date_str'])['date'].min()) 5sr_worktime_str = sr_worktime.apply(lambda td: f'{td.seconds//3600:02}:{(td.seconds%3600)%60:02}') 6sr_worktime_str.name = 'worktime' 7sr_work_sum = df.groupby(['person', 'date_str'])['work'].sum() 8sr_work_sum.name = 'work_sum' 9df_result = pd.concat([sr_worktime_str, sr_work_sum], axis=1).reset_index() 10print(df_result)

同一personの複数のdateの情報を集計できているかどうかの確認のためにデータを少し増やしてあります。

python

1>>> print(df) 2 person date work 30 A 2021-09-20 08:00:00 10 41 A 2021-09-20 10:00:00 20 52 A 2021-09-20 18:00:00 30 63 B 2021-09-19 09:00:00 15 74 B 2021-09-19 20:00:00 25 85 C 2021-09-19 09:00:00 15 96 C 2021-09-19 13:00:00 45 107 C 2021-09-19 17:00:00 20 118 C 2021-09-20 10:00:00 5 129 C 2021-09-20 15:00:00 40 1310 C 2021-09-20 19:00:00 35

実行結果

python

1>>> print(df_result) 2 person date_str worktime work_sum 30 A 2021/09/20 10:00 60 41 B 2021/09/19 11:00 40 52 C 2021/09/19 08:00 80 63 C 2021/09/20 09:00 80

詳しい使い方は以下を参照してください。

pandasで日付・時間の列を処理(文字列変換、年月日抽出など)
pandas.DataFrameをGroupByでグルーピングし統計量を算出
pandasで要素、行、列に関数を適用するmap, applymap, apply
timedelta オブジェクト

投稿2021/09/20 06:11

編集2021/09/20 06:17
ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

luria

2021/09/20 10:08

サンプルデータまで拡張してくださり、恐縮です。。 日付をIndexにしてそれをなんとかして使おうとしてはまってしまっていました。このように別カラムで扱えばいいのですね。 回答、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問