【问题标题】:Averaging a specific number of rows in DataFrame array平均 DataFrame 数组中的特定行数
【发布时间】:2015-07-29 07:16:20
【问题描述】:

我正在尝试在名为 ave_data 的 DataFrame 中获取以下时间的平均值(如下所示):

  1. 早上 5 点到 9 点(4 小时)
  2. 上午 9 点到下午 6 点(9 小时)
  3. 下午 6 点到晚上 10 点(4 小时)
  4. 晚上 10 点到早上 5 点(7 小时)

目前我的 'ave_data' DataFrame 输出以下数据(请忽略所有破折号,它们仅用于对齐数据):

时间 ---------- F1 ------------- F2 --------- --- F3
2082-05-03 00:00:00 --- 43.005593 --- -56.509746 --- 25.271271
2082-05-03 01:00:00 --- 55.114918 --- -59.173852 --- 31.849262
2082-05-03 02:00:00 --- 63.990762 --- -64.699492 --- 52.426017
2082-05-03 03:00:00 --- 56.508333 --- -65.489083 --- 36.188083
2082-05-03 04:00:00 --- 36.217295 --- -59.198033 --- 2.404426
2082-05-03 05:00:00 --- 36.153814 --- -62.156187 --- 24.779830
2082-05-03 06:00:00 --- 93.920334 --- -57.923000 --- 77.654250 ...

我想将这些新平均值保存为一个新的 DataFrame,如下所示(以下数字仅为随机示例):

时间 -------- F1 ------------- F2 ------------ - F3
早上(5AM-9AM) --- 50.005987 --- -60.509746 --- 29.311271
日(上午 9 点至下午 6 点)-------- 59.005987 --- -49.509746 --- 98.311271
晚上(6PM-10PM) -- 55.018887 --- -47.614622 --- 29.311271
晚上 (10PM-5AM) ---- 55.018887 --- -47.614622 --- 29.311271

另外,理想情况下,我希望添加最后一列,其中包含每行的平均值。该代码将用于读取不同的文件,这些文件将生成与下面显示的列数不同的列,因此,如果有人可以帮助我为此开发一种通用方法,那就太好了。

以下是我拥有的代码的相关部分:

raw_data = pd.read_excel(r'/Users/linnkloster/Desktop/Results/01_05_2012 Raw Results.xls', skiprows=1, header=0, nrows=1440, dayfirst=True, infer_datetime_format='%d/%m/%Y %H')
raw_data[u'Time']= pd.to_datetime(raw_data['Time'], unit='d')
# Converts first column to datetime, to make averaging easier
# Note this gets the wrong date (2082-05-03) but correct hour
raw_data.set_index(pd.DatetimeIndex(raw_data[u'Time']), inplace=True)
ave_data=raw_data.resample('h', how='mean')
print ave_data

【问题讨论】:

  • 您能否上传您的示例 xls 文件(例如,通过 Dropbox 共享链接或谷歌驱动程序)?对于盘中时段的抽样,有几个选项可供选择:.indexer_between_timepd.cut 表示午夜过后多少小时 (timedelta)。
  • 实际数据有点敏感,因为我有一个可行的解决方案,所以这次我不会上传它。谢谢你的好建议

标签: python arrays datetime pandas average


【解决方案1】:

您可以应用返回类别的函数:

import pandas as pd

data = [('2082-05-03 00:00:00', 43.005593, -56.509746, 25.271271),
('2082-05-03 01:00:00', 55.114918, -59.173852, 31.849262),
('2082-05-03 02:00:00', 63.990762, -64.699492, 52.426017),
('2082-05-03 03:00:00', 56.508333, -65.489083, 36.188083),
('2082-05-03 04:00:00', 36.217295, -59.198033, 2.404426),
('2082-05-03 05:00:00', 36.153814, -62.156187, 24.779830),
('2082-05-03 06:00:00', 93.920334, -57.923000, 77.654250)]

df = pd.DataFrame(data = data, columns=['Time', 'F1', 'F2', 'F3'])
df.Time = pd.to_datetime(df.Time)

def time_cat(t):
    hour = t.hour
    if hour < 5:
        return 'Night(10PM-5AM)'
    if hour < 9:
        return 'Morning(5AM-9AM)'
    if hour < 18:
        return 'Day(9AM-6PM)'
    if hour < 22:
        return 'Evening(6PM-10PM)'
    # if hour >= 22:
    return 'Night(10PM-5AM)'

df.groupby(df.Time.apply(time_cat)).mean()

                    F1          F2          F3
Time            
Morning(5AM-9AM)    65.037074   -60.039594  51.217040
Night(10PM-5AM)     50.967380   -61.014041  29.627812

【讨论】:

  • 这很好用。谢谢!我删除了 'columns=['Time', 'F1', 'F2', 'F3']' 因为这些标题会随着代码读取不同的文件(在代码文件的前面)而改变。由于某种原因,输出的顺序是:(第 1 行)白天,(第 2 行)晚上,然后是(第 3 行)早上和(第 4 行)晚上。这可能是一个简单的解决方法,但对于如何重新堆叠它们以使新的 DataFrame/Output 按顺序排列(第 1 行)早上,(2)白天,(3)晚上,(4)晚上有什么简单的想法吗?对不起,我对 Python 很陌生..
  • 一个快速的后续问题:我正在尝试将其用于另一个 DataFrame,该 DataFrame 是通过操作初始问题中的 raw_data DataFrame 创建的。但是,被操纵的 DataFrame 会丢失索引标头,因此我不能像您在上面的代码中那样调用“时间”。我尝试使用 df.index.name=u'Time' 再次分配索引标题,但它给了我以下错误:“ValueError:新名称的长度必须为 1,得到 4”关于如何解决此问题的任何想法所以我可以以同样的方式对这个新的 DataFrame(名为 outage_by_hour)进行排序?
  • 我不知道该信息有什么问题。可能应该只发布另一个问题,其中包含有关您如何创建其他数据框的更多背景信息。
  • 您能解释一下 df.Time 的“.Time”部分的作用吗?我很难通过这个函数运行另一个 DataFrame:outage_by_hour_num.Time= pd.to_datetime(outage_by_hour_num.Time) outage_by_timeofday =outage_by_hour_num.groupby(outage_by_hour_num.Time.apply(time_cat)).sum(axis=1, numeric_only= True) AttributeError: 'DataFrame' object has no attribute 'Time' 当我调用 outage_by_hour_num.index 时,我得到以下信息: DatetimeIndex( ... ) dtype='datetime64[ns]', name=u' Time' , freq='H', tz=None) - 暗示 DataFrame 确实有 'Time' 作为属性?
【解决方案2】:

这个怎么样?请注意,我添加了三列,所以我使用dfraw_data 的副本。如果没问题,你当然不需要副本。

def Time(hour):
    if(hour>=5 and hour<9):
        return 'Morning'
    elif(hour>=9 and hour<18):
        return 'Day'
    elif(hour>=18 and hour<22):
        return 'Evening'
    else:
        return 'Night'

df = raw_data.copy()
df['date'] = df.Time.apply(lambda time:time.date())
df['hour'] = df.Time.apply(lambda time:time.hour)
df['time']=df.hour.apply(Time)
ave_data=df.drop('hour',axis=1).groupby(['date','time']).mean()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 2013-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多