【问题标题】:How can I map two different time series to each other and perform calculations while mapping?如何将两个不同的时间序列相互映射并在映射时执行计算?
【发布时间】:2020-12-20 10:33:37
【问题描述】:

我有两个不同的包含时间序列数据的 CSV。一张桌子是连续的,从 01.01.2017 的 00:00 开始。从那里开始,每一行代表一小时(1. 表)。数据看起来像这样:

  1. 表格又名 df1:
Date,                   Volume
2017-02-03 12-PM,       9787.51
2017-02-03 01-PM,       9792.01
2017-02-03 02-PM,       9803.94
2017-02-03 03-PM,       9573.99

另一个表包含发生的事件,并由 UNIX 日期时间以秒为单位进行序列化。我能够将其转换为日期时间并使用以下代码按小时分组:

df['datetime'] = pd.to_datetime(df['created_utc'], unit='s')
df['datetime'] = pd.to_datetime(df['datetime'], format="%Y-%m-%d %I-%p")
df['date_by_hour'] = df['datetime'].apply(lambda x: x.strftime('%Y-%m-%d %H:00'))

这导致了以下数据:

  1. 表又名 df2:
created_utc,    score,      compound,   datetime,               date_by_hour
1486120391,     156,        0.125,      2017-02-03 12:13:11,    2017-02-03 12:00:00
1486125540,     1863,       0.475,      2017-02-03 13:39:00,    2017-02-03 13:00:00
1486126013,     863,        0.889,      2017-02-03 13:46:53,    2017-02-03 13:00:00
1486130203,     23,         0.295,      2017-02-03 14:56:43,    2017-02-03 14:00:00

现在我需要将事件 (2.table) 映射到 1. 表的时间序列。如果在一小时内发生了多个事件,我需要将分数相加并计算化合物的平均平均值。最后我想要一个这样的数据框:

  1. 最终数据帧
Date,                   Volume,         score,      compound,
2017-02-03 12-PM,       9787.51,        156,        0.125,
2017-02-03 01-PM,       9792.01,        2726,       0.682,
2017-02-03 02-PM,       9803.94,        23,         0.295,
2017-02-03 03-PM,       9573.99,        0,          0, 

我知道我下面的代码不起作用并且是错误的,但我想展示我在想如何实现这一点。我想我可以遍历我的事件表 df2 的每一行并比较日期时间是否匹配。如果是这样,我会计算分数和复合。问题是我知道不应该循环遍历数据帧,而且我不知道如何同时循环遍历另一个数据帧并根据前面的行执行正确的计算...

for index, row in df2.iterrows():
    memory_score = 0
    memory_compound = 0
    if df1['Date'] == df2['date_by_hour']:
        df1['score'] = row['score'] + memory_score
        df1['compound'] = (row['compound'] + memory_compound) / 2    

如何获得我的最终数据框?一定有一些 pandas 魔法可以用来完成这项工作并将时间序列数据映射到正确的时间。

提前致谢并致以最诚挚的问候

编辑:一小时内可以有未定义数量的事件。我只是为这个简单的示例选择了 2,但在某些情况下它可能是 5000 或其他值或 0。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:
    # import necessary packages, set seed
    
    import pandas as pd
    import datetime
    import random
    random.seed(42)
    

    设置

    让我们创建一个示例df1,使用this

    numdays=5
    base = datetime.datetime(2017,2,3,12)
    date_list = [base + datetime.timedelta(hours=x) for x in range(numdays)]
    

    那么,using

    df1 = pd.DataFrame.from_dict({'Date': date_list,
                                  'Volume': [random.randint(9000,11000) for _ in range(len(date_list))]})
    

    这给了我们:

    +----+---------------------+----------+
    |    | Date                |   Volume |
    |----+---------------------+----------|
    |  0 | 2017-02-03 12:00:00 |     9228 |
    |  1 | 2017-02-03 13:00:00 |     9051 |
    |  2 | 2017-02-03 14:00:00 |    10518 |
    |  3 | 2017-02-03 15:00:00 |     9563 |
    |  4 | 2017-02-03 16:00:00 |     9501 |
    +----+---------------------+----------+
    

    让我们也创建df2

    random_date_list = [base + datetime.timedelta(hours=x*random.uniform(0,2)) for x in range(7)]
    
    df2 = pd.DataFrame({'datetime':random_date_list,
                       'score':[random.randint(20,200) for _ in range(len(random_date_list))],
                       'compound': [random.uniform(0,1) for _ in range(len(random_date_list))]},
                       index=[x for x in range(len(random_date_list))])
    

    给出:

    +----+----------------------------+---------+------------+
    |    | datetime                   |   score |   compound |
    |----+----------------------------+---------+------------|
    |  0 | 2017-02-03 12:00:00        |      75 |   0.71602  |
    |  1 | 2017-02-03 13:28:22.592742 |      79 |   0.701325 |
    |  2 | 2017-02-03 14:42:24.472619 |     149 |   0.41952  |
    |  3 | 2017-02-03 17:21:11.078662 |     174 |   0.449209 |
    |  4 | 2017-02-03 12:41:43.838380 |      26 |   0.278191 |
    |  5 | 2017-02-03 16:13:09.185509 |     163 |   0.8693   |
    |  6 | 2017-02-03 12:21:27.239880 |      70 |   0.758807 |
    +----+----------------------------+---------+------------+
    

    实际计算

    让我们在 df2 中创建一个包含日期时间对象以小时分辨率的列:

    df2['Date'] = df2['datetime'].apply(lambda x: x.replace(minute=0, second=0, microsecond=0))
    

    我们可以merge df1 & df2, replace NaNs with 0s:

    merged = pd.merge(df1,df2,on='Date', how='outer')
    merged.fillna(0,inplace=True)
    

    现在计算所需的新列:

    newscoredf=merged.groupby('Date')[['score']].agg('sum')
    newcompounddf=merged.groupby('Date')[['compound']].agg('mean')
    

    让我们连接它们,并添加我们留下的Volume 列:

    final = pd.concat([df1.set_index('Date')[['Volume']],newscoredf,newcompounddf],axis=1)
    

    它给你你想要的。

    final:

    +---------------------+----------+---------+------------+
    | Date                |   Volume |   score |   compound |
    |---------------------+----------+---------+------------|
    | 2017-02-03 12:00:00 |     9228 |     171 |   0.584339 |
    | 2017-02-03 13:00:00 |     9051 |      79 |   0.701325 |
    | 2017-02-03 14:00:00 |    10518 |     149 |   0.41952  |
    | 2017-02-03 15:00:00 |     9563 |       0 | nan        |
    | 2017-02-03 16:00:00 |     9501 |     163 |   0.8693   |
    | 2017-02-03 17:00:00 |      nan |     174 |   0.449209 |
    +---------------------+----------+---------+------------+
    

    检查:考虑从 12 开始在一小时内发生的行。得分:得分:75+26+70 = 171。复合:(0.71602 + 0.278191 + 0.758807) / 3 = 0.584339。两者都与我们结果的第一行一致。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-20
      • 1970-01-01
      • 2022-12-07
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      相关资源
      最近更新 更多