Среднее значение 2 последовательных строк в данных Panda - PullRequest
2 голосов
/ 02 мая 2019

У меня есть набор данных, который выглядит следующим образом

userid time           val1 val2 val3 val4
1      2010-6-1 0:15  12   16   17   11
1      2010-6-1 0:30  11.5 14   15.2 10
1      2010-6-1 0:45  12   14   15   10
1      2010-6-1 1:00  8    11   13   0
.................................
.................................
2      2010-6-1 0:15  14   16   17   11
2      2010-6-1 0:30  11   14   15.2 10
2      2010-6-1 0:45  11   14   15   10
2      2010-6-1 1:00  9    11   13   0
.................................
.................................
3 ...................................
.................................
.................................

Я хочу получить среднее значение для каждых двух строк.Ожидаемые результаты будут

userid time           val1  val2  val3  val4
1      2010-6-1 0:30  11.75 15    16.1  10.5
1      2010-6-1 1:00  10    12.5  14    5
..............................
..............................
2      2010-6-1 0:30  12.5  15    16.1  10.5
2      2010-6-1 1:00  10    12.5  14    5
.................................
.................................
3 ...................................
.................................
.................................

На данный момент мой подход

data = pd.read_csv("sample_dataset.csv")
i = 0
while i < len(data) - 1:
    x = data.iloc[i:i+2].mean()
    x['time'] = data.iloc[i+1]['time']
    data.iloc[i] = x
    i+=2
for i in range(len(data)):
    if i % 2 != 1:
        del data.iloc[i]

Но это очень неэффективно.Поэтому кто-то может указать мне лучший подход, чтобы получить намеченный результат?В наборе данных у меня более 1000000 строк

Ответы [ 3 ]

5 голосов
/ 02 мая 2019

Я использую resample

df.set_index('time').resample('30Min',closed = 'right',label ='right').mean()
Out[293]: 
                      val1  val2  val3  val4
time                                        
2010-06-01 00:30:00  11.75  15.0  16.1  10.5
2010-06-01 01:00:00  10.00  12.5  14.0   5.0

Метод 2

df.groupby(np.arange(len(df))//2).agg(lambda x : x.iloc[-1] if x.dtype=='datetime64[ns]' else x.mean())
Out[308]: 
                 time   val1  val2  val3  val4
0 2010-06-01 00:30:00  11.75  15.0  16.1  10.5
1 2010-06-01 01:00:00  10.00  12.5  14.0   5.0

Обновление решения

df.groupby([df.userid,np.arange(len(df))//2]).agg(lambda x : x.iloc[-1] if x.dtype=='datetime64[ns]' else x.mean()).reset_index(drop=True)
2 голосов
/ 02 мая 2019

Это решение остается в pandas и гораздо более эффективно, чем решение groupby-agg:

>>> df = pd.DataFrame({"a":range(10),
                   "b":range(0, 20, 2),
                   "c":pd.date_range('2018-01-01', periods=10, freq='H')})
>>> df

   a   b                   c
0  0   0 2018-01-01 00:00:00
1  1   2 2018-01-01 01:00:00
2  2   4 2018-01-01 02:00:00
3  3   6 2018-01-01 03:00:00
4  4   8 2018-01-01 04:00:00
5  5  10 2018-01-01 05:00:00
6  6  12 2018-01-01 06:00:00
7  7  14 2018-01-01 07:00:00
8  8  16 2018-01-01 08:00:00
9  9  18 2018-01-01 09:00:00

>>> pd.concat([(df.iloc[::2, :2] + df.iloc[1::2, :2].values) / 2,
            df.iloc[::2, 2]], axis=1)

     a     b                   c
0  0.5   1.0 2018-01-01 00:00:00
2  2.5   5.0 2018-01-01 02:00:00
4  4.5   9.0 2018-01-01 04:00:00
6  6.5  13.0 2018-01-01 06:00:00
8  8.5  17.0 2018-01-01 08:00:00

Производительность:

In [41]: n = 100000

In [42]: df = pd.DataFrame({"a":range(n), "b":range(0, n*2, 2), "c":pd.date_range('2018-01-01', periods= n, freq='S')})

In [44]: df.shape
Out[44]: (100000, 3)

In [45]: %timeit pd.concat([(df.iloc[::2, :2] + df.iloc[1::2, :2].values) / 2, df.iloc[::2, 2]], axis=1)
2.21 ms ± 49.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [46]: %timeit df.groupby(np.arange(len(df))//2).agg(lambda x : x.iloc[-1] if x.dtype=='datetime64[ns]' else x.mean())
7.9 s ± 218 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
0 голосов
/ 03 мая 2019

Я пробовал оба упомянутых ответа.Оба работали.Но ответ Ноя был самым быстрым, как я понял.Поэтому я отметил этот ответ как решение.Вот моя версия ответа Ноя с некоторыми пояснениями и правками для сопоставления с моим набором данных

Чтобы использовать Ной, столбец времени ответа должен быть первым или последним (я, возможно, ошибаюсь).Поэтому я переместил столбец времени в конец

col = data.columns.tolist()
tmp = col[10]
col[10] = col[1]
col[1] = tmp
data2 = data[col]

Затем я сделал конкатенацию.Здесь :: 2 означает каждый второй столбец, а : 10 означает столбцы от 0 до 9. И затем я добавляю столбец времени, который находится в 10-м индексе

x = pd.concat([(data2.iloc[::2, :10] + data2.iloc[1::2, :10].values) / 2, data2.iloc[::2, 10]], axis=1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...