Лучший способ объединить множество временных рядов в pandas в один индекс даты-времени? - PullRequest
1 голос
/ 02 марта 2020

Я читаю много CSV-файлов. Каждый из них содержит данные временного ряда. Например:

import pandas as pd

csv_a = [['2019-05-25 10:00', 25, 60],
         ['2019-05-25 10:05', 26, 25],
         ['2019-05-25 10:10', 27, 63],
         ['2019-05-25 10:20', 28, 62]]
df_a = pd.DataFrame(csv_a, columns=["Timestamp", "Temperature", "Humidity"])
df_a["Timestamp"] = (pd.to_datetime(df_a["Timestamp"]))

csv_b = [['2019-05-25 10:05', 1020],
         ['2019-05-25 10:10', 1021],
         ['2019-05-25 10:15', 1019],
         ['2019-05-25 10:45', 1035]]
df_b = pd.DataFrame(csv_b, columns=["Timestamp", "Pressure"])
df_b["Timestamp"] = (pd.to_datetime(df_b["Timestamp"]))

После создания этих фреймов данных мы можем увидеть:

print(df_a)
            Timestamp  Temperature  Humidity
0 2019-05-25 10:00:00           25        60
1 2019-05-25 10:05:00           26        25
2 2019-05-25 10:10:00           27        63
3 2019-05-25 10:20:00           28        62

print(df_b)
            Timestamp  Pressure
0 2019-05-25 10:05:00      1020
1 2019-05-25 10:10:00      1021
2 2019-05-25 10:15:00      1019
3 2019-05-25 10:45:00      1035

Я хочу создать новый фрейм данных с регулярным индексом, например:

import datetime as dt

start = dt.datetime(2019,5,25,10,0,0)
end = dt.datetime(2019,5,25,10,20,0)
index = pd.date_range(start, end, freq='5min')

А затем начните добавлять каждый временной ряд в разные столбцы, заполняя пропущенные значения NaN и отбрасывая значения из моего индекса.

Желаемый результат:

                     Temperature  Humidity  Pressure
Timestamp                                           
2019-05-25 10:00:00         25.0      60.0       NaN
2019-05-25 10:05:00         26.0      25.0    1020.0
2019-05-25 10:10:00         27.0      63.0    1021.0
2019-05-25 10:15:00          NaN       NaN    1019.0
2019-05-25 10:20:00         28.0      62.0       NaN

И я Также хочу сделать это максимально эффективно. Допустим, у меня есть сотни CSV и длинные серии.

Я работаю с такими функциями Panda, как concat или append, но не могу получить то, что хочу.

Ответы [ 3 ]

3 голосов
/ 02 марта 2020

Как я понимаю, у вас уже был пользовательский индекс datetimeindex index, и вы хотите присоединиться к каждому временному ряду с помощью этого index. Попробуйте combine_first и reindex. Если у вас есть несколько временных рядов для присоединения, вам нужно использовать l oop или python reduce

df_out = df_b.combine_first(df_a).reindex(index)

Out[1063]:
                     Humidity  Pressure  Temperature
2019-05-25 10:00:00      60.0       NaN         25.0
2019-05-25 10:05:00      25.0    1020.0         26.0
2019-05-25 10:10:00      63.0    1021.0         27.0
2019-05-25 10:15:00       NaN    1019.0          NaN
2019-05-25 10:20:00      62.0       NaN         28.0

Если у вашего временного ряда нет одинаковых имен столбцов, Вы можете попробовать join. Просто перечислите временные ряды внутри скобки []

df_out = df_a.join([df_b], how='outer').reindex(index)

Out[1068]:
                     Temperature  Humidity  Pressure
2019-05-25 10:00:00         25.0      60.0       NaN
2019-05-25 10:05:00         26.0      25.0    1020.0
2019-05-25 10:10:00         27.0      63.0    1021.0
2019-05-25 10:15:00          NaN       NaN    1019.0
2019-05-25 10:20:00         28.0      62.0       NaN
2 голосов
/ 02 марта 2020

Использование DataFrame.merge. Вы можете проверить с помощью Series.diff, чтобы отбросить строки, в которых есть временный скачок, превышающий период. Но вы можете выбрать другой критерий для исключения строк (дайте мне знать, если вы хотите выбрать другой критерий)

df2 = (df_a.merge(df_b, on='Timestamp', how='outer')
           .sort_values('Timestamp'))
diff=df2['Timestamp'].diff().abs().bfill()
mask=diff.eq(diff.min())
new_df=(df2.loc[mask]
           .set_index('Timestamp')
       )
print(new_df)


#                     Temperature  Humidity  Pressure
#Timestamp                                           
#2019-05-25 10:00:00         25.0      60.0       NaN
#2019-05-25 10:05:00         26.0      25.0    1020.0
#2019-05-25 10:10:00         27.0      63.0    1021.0
#2019-05-25 10:15:00          NaN       NaN    1019.0
#2019-05-25 10:20:00         28.0      62.0       NaN

Вы можете выбрать частоту и исключить тех, кто не не выполняйте

df2 = (df_a.merge(df_b, on='Timestamp', how='outer')
           .set_index('Timestamp')
        )

new_df=(df2.reindex(pd.date_range(df2.index.min(),df2.index.max(),freq='5min'))
           .loc[lambda x: x.isna().all(axis=1).cumsum().eq(0)])

или просто вводите нижний и верхний пределы статически, как вы говорите в своем вопросе

1 голос
/ 02 марта 2020

Вы пробовали pd.merge?

pd.merge(df_a, df_b, how='outer').set_index('Timestamp').sort_index()

вывод:

                     Temperature  Humidity  Pressure
Timestamp                                           
2019-05-25 10:00:00         25.0      60.0       NaN
2019-05-25 10:05:00         26.0      25.0    1020.0
2019-05-25 10:10:00         27.0      63.0    1021.0
2019-05-25 10:15:00          NaN       NaN    1019.0
2019-05-25 10:20:00         28.0      62.0       NaN
2019-05-25 10:45:00          NaN       NaN    1035.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...