我是python的菜鸟,我需要使用pandas apply转换此代码的帮助
for i in range(len(mp10)):
currentEquipo = mp10['equipo'][i]
currentFechaInicial = mp10['fechaInicial'][i]
currentFechaFinal = mp10['fechaFinal'][i]
currentMes = mp10['mes'][i] - 1
for j in range(len(dFrames[currentMes])):
currentDF = dFrames[currentMes].copy()
if currentFechaInicial <= currentDF['Fecha'][i] <= currentFechaFinal:
currentDF[currentEquipo][i] = 1
我有两个数据框,一个是mp10,而dFrames是df的列表,在mp10中,我有不同的采矿设备,被拘留的起始日期和最终日期。
dFrames =(ene_17,feb_17,....,dic_17)
dFrames在每一列中都充满零,并且在停止时我需要填写一个。相对于mp10的开始日期和结束日期。
此代码取决于设备的dFrame以及其停止的日期。
最后,我需要使用apply函数来完成同一段代码
答案 0 :(得分:0)
为了更好地理解其他(非西班牙语)读者,我更改了 DataFrame /列名称转换为英语。
据我所知,您:
让我们从如何创建输入DataFrame开始吧:
usage = pd.DataFrame([
['PA01', '2017-01-01 07:18', '2017-01-01 09:00'],
['PA01', '2017-01-01 09:00', '2017-01-01 11:44'],
['PA03', '2017-01-01 09:45', '2017-01-01 11:31'],
['PA02', '2017-01-01 21:28', '2017-01-01 23:20'],
['PA02', '2017-01-01 09:00', '2017-01-01 10:29'],
['PA01', '2017-02-03 09:00', '2017-02-03 13:10']],
columns=['equipment', 'tmFrom', 'tmTo'])
usage.tmFrom = pd.to_datetime(usage.tmFrom)
usage.tmTo = pd.to_datetime(usage.tmTo)
对于该测试,我获取了1月和2月的一些数据( 数据超过一个月)。
第一步是定义一个函数来计算 给定的行( Numpy 数组):
def usageHours(row):
hrs = pd.date_range(row.tmFrom.ceil('H'), row.tmTo, freq='H')
nHrs = hrs.size # Number of full hours
return np.array([hrs.tolist(), [row.equipment] * nHrs, [1] * nHrs]).T
例如对于我的测试数据的第一行,此函数返回:
[[Timestamp('2017-01-01 08:00:00', freq='H'), 'PA01', 1],
[Timestamp('2017-01-01 09:00:00', freq='H'), 'PA01', 1]]
上述数组的每一行都包含:
然后在使用设备时计算“全时” DataFrame(对于所有设备 输入数据):
usageTmp = pd.DataFrame(np.concatenate(usage.apply(usageHours, axis=1)),
columns=['dtm', 'eqpmt', 'usage']).drop_duplicates()
想法是:
最终结果的计算可以用单表示, 尽管链接非常紧密,但涉及到 pivot 和许多 “清理”步骤:
hourlyUsage = usageTmp.pivot(index='dtm', columns='eqpmt')\
.fillna(0, downcast='infer').droplevel(0, axis=1)\
.rename_axis(None, axis=1).rename_axis(None)\
.reindex(pd.date_range('2017-01-01 00:00', '2017-12-31 23:00',
freq='H'), fill_value=0)
以上解决方案的速度源于以下技巧:
如果您要查看结果并与源数据进行比较, 不要显示完整的数据框,因为“仅零”行的数量为 太大。而是只显示包含任何列!= 0 :
的行hourlyUsage[hourlyUsage.any(axis=1)]
我认为,这种解决方案比您的循环更“泛滥”。 如果可以,请检查解决方案的执行时间,然后挖掘并编写 对此发表评论。
最后一点:目前,您有一个单个 DataFrame用于 全年。如果您确实想要一个“每月”数据框架列表, 运行:
hourlyUsageByMonth = [
hourlyUsage[hourlyUsage.index.month == m].copy()
for m in hourlyUsage.index.month.unique() ]
请注意,我使用了 .copy()创建“独立的” DataFrame, 每个都有自己的数据缓冲区,而不是原始DataFrame的视图。