Уточнение временного ряда Python: из 'секунд' в 'секунды.микросекунды'

Есть таблица данных df с временным рядом datetime - показания прибора, который снимает данные от 1010 до 1030 раз в секунду (варьируется от количества успевших проскочить по кабелю за секунду пакетов). И у всех 1010-1030 показаний характеристик (которых всего 22, но это мы опустим) одинаковое значение datetime. Условно выглядит следующим образом:

>>> 2022-06-17 08:21:51     13819   1.07
>>> 2022-06-17 08:21:51     13820   1.08
>>> 2022-06-17 08:21:51     13821   1.07
>>> 2022-06-17 08:21:51     13822   1.08
>>> 2022-06-17 08:21:51     13823   1.08
.  .  .
>>> 2022-06-17 08:21:52     14724   1.08
>>> 2022-06-17 08:21:52     14725   1.08
>>> 2022-06-17 08:21:52     14726   1.08
.  .  .
>>> 2022-06-17 08:21:53     15527   1.09
>>> 2022-06-17 08:21:53     15528   1.09
>>> 2022-06-17 08:21:53     15529   1.09
>>> 2022-06-17 08:21:53     15530   1.09

Необходимо получить таблицу, в которой значения 'datetime' для каждой секунды разбиваются на микросекунды. Посчитал количество разбиений для каждого шага

counters=df.groupby(df['datetime'].tolist(),as_index=True).size()

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

pd.Timedelta(pd.offsets.Micro(round(1/counters[j]*1000000,0)))

Но как правильно реализовать это в цикле - что-то допетрить не могу. Такая реализация:

for i in df.index:
    for j in counters.index:
        countsum=pd.Timedelta(pd.offsets.Micro(0))
        if df.iloc[i]['datetime'] == j: 
            df.iloc[i]['datetime']+=countsum
            countsum+=pd.Timedelta(pd.offsets.Micro(round(1/counters[j]*1000000,0)))

Не работает. Пишет: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame


Ответы (2 шт):

Автор решения: strawdog

я не уверен, что правильно понял вопрос, однако могу предложить такое не особо изящное решение:

import pandas as pd
import numpy as np
from io import StringIO

data = '''2022-06-17 08:21:51,13819,1.07
2022-06-17 08:21:51,13820,1.08
2022-06-17 08:21:51,13821,1.07
2022-06-17 08:21:51,13822,1.08
2022-06-17 08:21:51,13823,1.08
2022-06-17 08:21:52,14724,1.08
2022-06-17 08:21:52,14725,1.08
2022-06-17 08:21:52,14726,1.08
2022-06-17 08:21:53,15527,1.09
2022-06-17 08:21:53,15528,1.09
2022-06-17 08:21:53,15529,1.09
2022-06-17 08:21:53,15530,1.09'''
df = pd.read_csv(StringIO(data), index_col=0, parse_dates=[0], header=None)

res = pd.DataFrame()
for i, g in df.groupby(df.index):
    lims = [min(g[1]), max(g[1])]
    r = pd.DataFrame(index=pd.date_range(start=i, periods=1000000, freq='U'),
                     data = np.linspace(lims[0], lims[1], 1000000))

    res = pd.concat([res, r])

тогда

print(res.head())
print(res.tail())

дадут:

                                       0
2022-06-17 08:21:51.000000  13819.000000
2022-06-17 08:21:51.000001  13819.000004
2022-06-17 08:21:51.000002  13819.000008
2022-06-17 08:21:51.000003  13819.000012
2022-06-17 08:21:51.000004  13819.000016

и

                                       0
2022-06-17 08:21:53.999995  15529.999988
2022-06-17 08:21:53.999996  15529.999991
2022-06-17 08:21:53.999997  15529.999994
2022-06-17 08:21:53.999998  15529.999997
2022-06-17 08:21:53.999999  15530.000000​

соответственно

UPDATE

Если нужно просо сделать индекс уникальным, равномерно распределив значения для каждой секунды, то можно попробовать так:

res = pd.DataFrame()
for i, g in df.groupby(df.index):
    t = pd.date_range(start=i, end=i+pd.DateOffset(seconds=1), periods=len(g))
    g = g.set_index(t)
    res = pd.concat([res, g])

res:

                                   1     2
2022-06-17 08:21:51.000000000  13819  1.07
2022-06-17 08:21:51.250000000  13820  1.08
2022-06-17 08:21:51.500000000  13821  1.07
2022-06-17 08:21:51.750000000  13822  1.08
2022-06-17 08:21:52.000000000  13823  1.08
2022-06-17 08:21:52.000000000  14724  1.08
2022-06-17 08:21:52.500000000  14725  1.08
2022-06-17 08:21:53.000000000  14726  1.08
2022-06-17 08:21:53.000000000  15527  1.09
2022-06-17 08:21:53.333333333  15528  1.09
2022-06-17 08:21:53.666666666  15529  1.09
2022-06-17 08:21:54.000000000  15530  1.09
→ Ссылка
Автор решения: SergFSM

у меня получилось сделать вот таким неказистым способом:

df['datetime'] = df['datetime'] + (pd.to_timedelta(df.groupby('datetime')
                                                   .apply(lambda x: x.assign(d=round(1000000/len(x)))
                                                          .cumsum().shift().fillna(0))['d']))

>>> df
'''
                        datetime      1     2
0  2022-06-17 08:21:51.000000000  13819  1.07
1  2022-06-17 08:21:51.000200000  13820  1.08
2  2022-06-17 08:21:51.000400000  13821  1.07
3  2022-06-17 08:21:51.000600000  13822  1.08
4  2022-06-17 08:21:51.000800000  13823  1.08
5  2022-06-17 08:21:52.000000000  14724  1.08
6  2022-06-17 08:21:52.000333333  14725  1.08
7  2022-06-17 08:21:52.000666666  14726  1.08
8  2022-06-17 08:21:53.000000000  15527  1.09
9  2022-06-17 08:21:53.000250000  15528  1.09
10 2022-06-17 08:21:53.000500000  15529  1.09
11 2022-06-17 08:21:53.000750000  15530  1.09
→ Ссылка