Pandas dataframe interpolation with logarithmically sampled time intervals

Viewed 186

I have a pandas dataframe with columns 'Time' in minutes and 'Value' pulled in from a data logger. The data are logged in logarithmic time intervals, meaning that the first values are logged in fractional minutes then as time proceeds the time intervals get longer:

print(df)
      Minutes   Value
0       0.001    0.00100
1       0.005    0.04495
2       0.010    0.04495
3       0.015    0.09085
4       0.020    0.11368
..        ...        ...
561  4275.150  269.17782
562  4285.150  266.90964
563  4295.150  268.35306
564  4305.150  269.42984
565  4315.150  268.37594

I would like to linearly interpolate the 'Value' at one minute intervals from 0 to 4315 minutes.

I have attempted a few different iterations of df.interpolate() however have not found success. Can someone please help me out? Thank you

2 Answers

I think it's possible that my question was very basic or I made a confusing question. Either way I just wrote a little loop to solve my problem and felt like I should share it. I am sure that this not the most efficient way of doing what I was asking and hopefully somebody could suggest better ways of accomplishing this. I am still very new a this whole thing.

First a few qualifying things:

  1. The 'Value' data that I was talking about is called 'drawdown', which refers to a difference in water level from the initial starting water level inside a water well. It starts at 0.

  2. This kind of data is often viewed in a semi-log plot and sometimes its easier to replace 0 with a very low number instead (i.e 0.0001) so that it plots easy in other programs.

This code takes a .csv file with column names 'Minutes' and 'Drawdown' and compares time values with a new reference dataframe of minutes from 0 through the end of the dataset. It references the 2 closest time values to the desired time value in the list and makes a weighted average of those values then creates a new csv of the integer minutes with drawdown.

Cheers!

# -*- coding: utf-8 -*-
"""
Created on Tue Sep 22 13:42:29 2020

@author: cmeyer
"""

import pandas as pd
import numpy as np

df=pd.read_csv('Read_in.csv')
length=len(df)-1
last=df.at[length,'Drawdown']
lengthpump=int(df.at[length,'Minutes'])
minutes=np.arange(0,lengthpump,1)
dfminutes=pd.DataFrame(minutes)
dfminutes.columns = ['Minutes']
for i in range(1, lengthpump, 1):

    non_uni_minutes=df['Minutes']
    uni_minutes=dfminutes.at[i,'Minutes']

    close1=non_uni_minutes[np.argsort(np.abs(non_uni_minutes-uni_minutes))[0]]
    close2=non_uni_minutes[np.argsort(np.abs(non_uni_minutes-uni_minutes))[1]]

    index1 = np.where(non_uni_minutes == close1)
    index1 = int(index1[0])
    index2 = np.where(non_uni_minutes == close2)
    index2 = int(index2[0])

    num1=df.at[index1,'Drawdown']
    num2=df.at[index2,'Drawdown']

    weight1 = 1-abs((i-close1)/i)
    weight2 = 1-abs((i-close2)/i)

    Value = (weight1*num1+weight2*num2)/(weight1+weight2)

    dfminutes.at[i,'Drawdown'] = Value
dfminutes.at[0,'Drawdown'] = 0.000001
dfminutes.at[0,'Minutes'] = 0.000001
dfminutes.to_csv('integer_minutes_drawdown.csv')

Here I implemented efficient solution using numpy.interp. I've coded a bit fancy way of reading-in data into pandas.DataFrame from string, you may use any simpler suitable way for your needs like pandas.read_csv(...).

Try next code here online!

import math
import pandas as pd, numpy as np

# Here is just fancy way of reading data, use any other method of reading instead
df = pd.DataFrame([map(float, line.split()) for line in """
   0.001    0.00100
   0.005    0.04495
   0.010    0.04495
   0.015    0.09085
   0.020    0.11368
4275.150  269.17782
4285.150  266.90964
4295.150  268.35306
4305.150  269.42984
4315.150  268.37594
""".splitlines() if line.strip()], columns = ['Time', 'Value'])

a = df.values
# Create array of integer x = [0 1 2 3 ... LastTimeFloor].
x = np.arange(math.floor(a[-1, 0] + 1e-6) + 1)
# Linearly interpolate
y = np.interp(x, a[:, 0], a[:, 1])

df = pd.DataFrame({'Time': x, 'Value': y})
print(df)
Related