Лучший способ уменьшить выборку (уменьшить частоту дискретизации) данных, не относящихся к временным рядам, в Панд

#python #pandas #dataframe

Вопрос:

У меня есть фрейм данных, содержащий данные, собранные каждые 0,01 м вглубь земли. Благодаря высокому разрешению результирующий размер набора данных очень велик. Есть ли в pandas способ уменьшить количество интервалов до 5 м, тем самым уменьшив размер набора данных?

РЕЗУЛЬТАТ (Каждые 0,01 м)

Глубина_м ценность
1.34 31.7
1.35 31.7
1.36 31.7
1.37 31.9
1.38 31.9
1.39 31.9
1.40 31.9
…. …..
44.35 32.9
44.36 32.9
44.37 32.9

РЕЗУЛЬТАТ, КОТОРОГО Я ХОЧУ (Каждые 5 м)

Глубина_м ценность
5.47 31.7
10.49 31.7
15.51 31.7
20.53 31.9
25.55 31.9
30.57 31.9
35.59 31.9
40.61 31.9
45.63 31.9

Я пытался использовать pandas.resample , но, похоже, это работает только с данными временных рядов. Я думаю, что понимаю, что я должен делать, но не уверен, как это сделать в панд. В основном я думаю, что мне нужно рассчитать текущую частоту дискретизации, в данном случае 0,01 м. Тогда сколько наблюдений происходит каждые 5 метров. Затем я могу усреднить значения на основе количества наблюдений и удалить строки. Повторяйте этот процесс каждые 5 метров.

Комментарии:

1. Я понизил голос, потому что: вопрос не воспроизводим, содержит числовые данные в виде изображения, не показывает никаких попыток решения проблемы.

2. Извините, что в первый раз публикую, пытаясь сделать это более понятным

Ответ №1:

resample Для целочисленных значений нет. В качестве обходного пути вы можете округлить глубину до ближайших 5 и использовать groupby для получения среднего значения для каждой глубины 5 м.:

 >>> df.groupby(df["Depth_m"].apply(lambda x: 5*round(x/5)))["Value"].mean()
Depth_m
0     34.256410
5     34.274549
10    34.564870
15    34.653307
20    34.630739
25    34.517034
30    34.584830
35    34.581162
40    34.620758
45    34.390374
Name: Value, dtype: float64
 
Вход df:
 import numpy as np
np.random.seed(100)

df = pd.DataFrame({"Depth_m": [i/100 for i in range(134, 4438)],
                   "Value": np.random.randint(30, 40, size=4304)})
 

Ответ №2:

Вы можете использовать Panda .iloc для выбора по положению в сочетании с объектом среза для уменьшения выборки. Необходимо позаботиться о том, чтобы у вас были целочисленные размеры шага, а не плавающие значения при преобразовании из нецелочисленных интервалов выборки (отсюда использование astype("int") ).

 import numpy as np
import pandas as pd

sequence_interval = 0.01
downsampled_interval = 5
step_size = np.round(downsampled_interval / sequence_interval).astype("int")

df = pd.DataFrame(
    {
        "Depth_m": np.arange(131, 4438) / 100,
        "value": np.random.random(size=4307),
    }
)

downsampled_df = df.iloc[::step_size, :]
print(downsampled_df)
 

В результате получается

       Depth_m     value
0        1.31  0.357536
500      6.31  0.384327
1000    11.31  0.302109
1500    16.31  0.200971
2000    21.31  0.689973
2500    26.31  0.712869
3000    31.31  0.776306
3500    36.31  0.221901
4000    41.31  0.661378