如何确定数据框中不同子集的每月运行时间?

时间:2018-04-11 14:07:41

标签: python pandas datetime dataframe intervals

我是python的新手并且正在努力解决以下问题;

我有以下字段的数据框构建:日期','机器类型','总运行时间'

Date      Machine   TRH

27-02-2018  ...     ... 
01-03-2018   A      2200
01-03-2018   B      5700
02-03-2018   A      2204
09-03-2018   B      5709
15-03-2018   B      5715
18-03-2018   A      2214
25-03-2018   A      2222
29-03-2018   B      5720
31-03-2018   A      2230
01-04-2018  ...     ...

我想确定每种类型的机器运行的每月小时数,并将其存储在附加列中。

每月营业时间可由下一个公式决定: 本月持续日期的小时数 - 该月第一天的小时数

对于机器A:(2230 - 2200)= 30

对于机器B:(5720 - 5700)= 20

结果应该是:

Date      Machine   TRH     Monthly TRH

27-02-2018  ...     ...        ...
01-03-2018   A      2200       30
01-03-2018   B      5700       20
02-03-2018   A      2204       30
09-03-2018   B      5709       20
15-03-2018   B      5715       20
18-03-2018   A      2214       30
25-03-2018   A      2222       30
29-03-2018   B      5720       20
31-03-2018   A      2230       30
01-04-2018  ...     ...        ...

我不知道如何解决这个问题。我应该使用groupby吗?我应该参考labda吗?我希望你们中的一个能回答我的问题。非常感谢!

2 个答案:

答案 0 :(得分:1)

'''
Date      Machine   TRH
01-03-2018   A      2200
01-03-2018   B      5700
02-03-2018   A      2204
09-03-2018   B      5709
15-03-2018   B      5715
18-03-2018   A      2214
25-03-2018   A      2222
29-03-2018   B      5720
31-03-2018   A      2230
'''

df = pd.read_clipboard()
df.Date = pd.to_datetime(df.Date, dayfirst = True)
df.set_index(pd.DatetimeIndex(df.Date), inplace = True)
df.TRH = pd.to_numeric(df.TRH).copy()

monthly = (df.groupby([pd.Grouper(freq = 'M'), 'Machine']).TRH.last() - df.groupby([pd.Grouper(freq = 'M'), 'Machine']).TRH.first()).to_frame(name = 'Monthly TRH').reset_index()

monthly['month'] = monthly.Date.dt.to_period('M')
monthly.drop('Date', axis = 1, inplace = True)
df['month'] = df.Date.dt.to_period('M')

df.merge(monthly).drop('month', axis = 1)

out

修改

第一种方法更快,但这是另一种方法:

'''
Date      Machine   TRH
01-03-2018   A      2200
01-03-2018   B      5700
02-03-2018   A      2204
09-03-2018   B      5709
15-03-2018   B      5715
18-03-2018   A      2214
25-03-2018   A      2222
29-03-2018   B      5720
31-03-2018   A      2230
'''

# clean up
df = pd.read_clipboard().sort_values('Date')
df.Date = pd.to_datetime(df.Date, dayfirst = True)
df['month'] = df.Date.dt.to_period('M')
df.TRH = pd.to_numeric(df.TRH).copy()

# do it in one go
df.groupby([
    'month',
    'Machine'
]).nth([
    0,
    -1
]).groupby([
    'month',
    'Machine'
]).diff().drop(columns = 'Date').dropna().reset_index().rename(columns = {
    'TRH' : 'Monthly TRH'
}).merge(df).drop(columns = 'month')

结果相同,列顺序不同。

alternate

答案 1 :(得分:0)

我猜测有人会提出比2组更好的方法,但这会有效。

首先对日期进行排序(确保它们是日期时间),然后将firstlast与groupby机器和月份一起使用(如果数据超过1年,则使用年份)。

import pandas as pd
df['Date'] = pd.to_datetime(df.Date, format='%d-%m-%Y')
df['Year'] = df.Date.dt.year
df['Month'] = df.Date.dt.month

df.sort_values(by='Date', inplace=True)
temp = (df.groupby(['Machine', 'Year', 'Month'])['TRH'].last()-
 df.groupby(['Machine', 'Year', 'Month'])['TRH'].first()).reset_index().rename(columns={'TRH': 'Monthly TRH'}

#  Machine  Year  Month  Monthly TRH
#0       A  2018      3         30.0
#1       B  2018      3         20.0

然后把它带回来你可以合并

df.merge(temp, on=['Month', 'Year', 'Machine'], how='left').drop(columns=['Month', 'Year'])

#         Date Machine     TRH  Monthly TRH
#0  2018-02-27     ...     ...          ...
#1  2018-03-01       A  2200.0         30.0
#2  2018-03-02       A  2204.0         30.0
#3  2018-03-18       A  2214.0         30.0
#4  2018-03-25       A  2222.0         30.0
#5  2018-03-31       A  2230.0         30.0
#6  2018-03-01       B  5700.0         20.0
#7  2018-03-09       B  5709.0         20.0
#8  2018-03-15       B  5715.0         20.0
#9  2018-03-29       B  5720.0         20.0
#10 2018-04-01     ...     ...          ...