Интерполиране на липсващи стойности в Python

Всички - надявам се, че ще можете да помогнете, тъй като това е една от онези задачи, за които знам, че почти съм се провалил от различните публикации тук и онлайн, но не ми се получи съвсем.

По същество имам следните данни в база данни, която се връща към обект на Pandas чрез psql.read_sql(sql, cnxn)

+------------------------------------+
|              StartTime  StartLevel |
+------------------------------------+
| 0  2015-02-16 00:00:00     480.000 |
| 1  2015-02-16 00:30:00     480.000 |
| 2  2015-02-16 00:34:00     390.000 |
| 3  2015-02-16 01:00:00     390.000 |
| 4  2015-02-16 01:30:00     390.000 |
| 5  2015-02-16 02:00:00     480.000 |
| 6  2015-02-16 02:17:00     420.000 |
+------------------------------------+

StartTime     datetime64[ns]
StartLevel           float64
dtype: object

Просто искам да завърша с интерполация минута по минута на горните данни.

Също така създадох поредица от дати и часове на минутна честота, но за живота си не мога да се справя с това да „картографирам“ таблицата си върху това и след това да интерполирам или как бих могъл да преобразувам началния час в минутна детайлност и след това да интерполирам липсващите данни .

Всяко съдействие ще бъде много оценено (и съм сигурен, че ще се напукам, когато намеря решението!) - Много благодаря

АКТУАЛИЗАЦИЯ

Следвайки предложенията по-долу, кодът е както следва:

import datetime
import numpy as np
import pandas as pd
import pyodbc
import pandas.io.sql as psql


cnxn = pyodbc.connect('DSN=MySQL;DATABASE=db;UID=uid;PWD=pwd')
cursor = cnxn.cursor()
sql = """
    SELECT
    StartTime,StartLevel
FROM
    aa.bb
    where cc = 'dd'
    and StartTime < '2015-02-16 02:30:00'
    order by StartTime asc"""

old_df = psql.read_sql(sql, cnxn)


num_minutes = 120
base = datetime.datetime(2015, 02, 16, 00, 00, 00)
date_list = [base + datetime.timedelta(minutes=x) for x in range(0, num_minutes)]
# set num_minutes for whatever is the correct number of minutes you require
new_data = [dict(StartTime=d, fake_val=np.NaN) for d in date_list]
new_df = pd.DataFrame(new_data)
new_df['StartLevel'] = old_df['StartLevel']
new_df.interpolate(inplace=True)

изходът от new_df при подканата е:

+-----------------------------------------------+
|              StartTime  fake_val  StartLevel  |
+-----------------------------------------------+
| 0   2015-02-16 00:00:00       NaN         480 |
| 1   2015-02-16 00:01:00       NaN         480 |
| 2   2015-02-16 00:02:00       NaN         390 |
| 3   2015-02-16 00:03:00       NaN         390 |
| 4   2015-02-16 00:04:00       NaN         390 |
| 5   2015-02-16 00:05:00       NaN         480 |
| 6   2015-02-16 00:06:00       NaN         480 |
+-----------------------------------------------+

person Patrick A    schedule 17.02.2015    source източник


Отговори (1)


Сигурен съм, че това не е най-питоничният отговор, така че приветствам коментари за подобряването му, но вярвам, че можете да направите нещо подобно

Първо създайте всички обекти за дата и час, за които искате стойности

num_minutes = 120
base = datetime.datetime(2015, 02, 16, 00, 00, 00)
date_list = [base + datetime.timedelta(minutes=x) for x in range(0, num_minutes)]
# set num_minutes for whatever is the correct number of minutes you require

След това създайте „фалшива“ рамка с тези стойности на индекса

new_data = [dict(StartTime=d, fake_val=np.NaN) for d in date_list]
new_df = pd.DataFrame(new_data)

РЕДАКТИРАНЕ: Коригиран отговор

Сега искаме да обединим двата кадъра с данни в един (и да сортираме по дата):

final_df = new_df.merge(df, how='outer', on='date').sort(columns='date')

final_df вече ще бъде сортирано по дата и ще съдържа правилните стойности за StartLevel, когато сте имали данни, и NaN, когато не сте имали данни за него. Тогава можете да се обадите на interpolate

РЕДАКТИРАНЕ: Interpolate не се нарича inplace по подразбиране, така че или трябва да зададете този флаг, или да запазите резултата

final_df = final_df.interpolate()

or

final_df.interpolate(inplace=True)

Очевидно колоната fake_val може да бъде изхвърлена, след като обедините добрите данни. Целта на създаването на тази рамка от данни е да имате една индексирана с всички стойности, които искате (тук съм сигурен, че има по-питоничен отговор)

Пълната документация за interpolate може да бъде намерена тук

person sedavidw    schedule 17.02.2015
comment
Благодаря за предложението, но не работи съвсем, тъй като генерира списъка с времена по минути, колона с NaN и след това просто картографира оригиналните StartTimes върху това - person Patrick A; 17.02.2015
comment
@PatrickA Обадихте ли се на interpolate()? Възможно е да не запазвате резултата. Разглеждайки документацията, това не се прави автоматично на място, така че можете да направите нещо като new_df = new_df.interpolate() или new_df.interpolate(inplace=True). Редактирах отговора, за да отразя това - person sedavidw; 17.02.2015
comment
Вярвам, че е така. Той генерира правилните времеви серии минута по минута и NaN в колоните fake_val. Също така изглежда интерполира последната стойност до края на минута по минута, но не интерполира StartLevel - бих искал да публикувам резултата за вас тук, но не съм сигурен как да - person Patrick A; 17.02.2015
comment
@PatrickA Можете ли да редактирате въпроса си и да го поставите там? Ако можете да включите кода, който сте използвали, това също би било полезно - person sedavidw; 17.02.2015
comment
Готово - публикувано в оригиналния въпрос - person Patrick A; 17.02.2015
comment
@PatrickA А, виждам проблема. Бях мързелив да прочета изхода си и се извинявам, току-що актуализирах отговора си, опитайте това - person sedavidw; 18.02.2015