Как нарезать группы к ближайшему n-му наблюдению - PullRequest
0 голосов
/ 12 июня 2018

У меня есть набор данных временного ряда, который выглядит примерно так:

Time   ID   X_Pos   Y_Pos
1      1    150     300
2      1    160     310
3      1    156     500
4      2    300     439 
5      2    200     500
6      3    500     320
7      3    400     230
8      3    500     540
9      3    450     600
10     3    400     600

Мне нужно по существу округлить количество наблюдений в пределах каждого идентификатора до ближайшего n-го числа, в этом примере я буду использоватьближайший 2. Это должно привести к набору данных, который будет выглядеть следующим образом:

Time   ID   X_Pos   Y_Pos
1      1    150     300
2      1    160     310
4      2    300     439 
5      2    200     500
6      3    500     320
7      3    400     230
8      3    500     540
9      3    450     600

Как видите, точное количество строк, оставшихся в каждой группе, отличается в зависимости от начального размера группы, но всегда остаетсякратное 2.

Я довольно близко подошел к получению того, что мне нужно, с помощью приведенного ниже кода, но пропускаю последний шаг (отмеченный вопросительными знаками):

grouped = data.groupby('ID')
timesteps = 2

def round_down(num, divisor):
    return num - (num%divisor)

endSlice = pd.DataFrame(round_down(grouped.size(), timesteps)).reset_index()

slicedData = data.groupby('ID', as_index = False).apply(lambda x: x.iloc[0: ???????])

РЕДАКТИРОВАТЬ Вопрос в том, что мне нужно поместить в ту часть кода, где находятся знаки вопроса, чтобы получить желаемый набор данных (т. Е. Второй набор данных), ИЛИ, есть ли более эффективныйспособ достижения этого набора данных?

Я думаю, что часть кода, где находятся знаки вопроса, просто должна ссылаться на значение endSlice для каждого идентификатора, но я довольноновичок в Python и отсутствие некоторых знаний о подобных вещах.

Заранее благодарен за любую помощь и извинения, если на этот вопрос был дан ответ в другом месте.

1 Ответ

0 голосов
/ 12 июня 2018

Если я правильно понимаю, вы можете сделать это:

# Set the multiple that you want the size of each group to be:
n = 2

# Groupby ID, then apply .head() to get the size you want:
df.groupby('ID').apply(lambda x: x.head(len(x) - len(x) % n)).reset_index(drop=True)

   Time  ID  X_Pos  Y_Pos
0     1   1    150    300
1     2   1    160    310
2     4   2    300    439
3     5   2    200    500
4     6   3    500    320
5     7   3    400    230
6     8   3    500    540
7     9   3    450    600

Обратите внимание, что это по существу эквивалентно вашей попытке с iloc, и нет необходимости в функции round_down:

df.groupby('ID').apply(lambda x: x.iloc[:len(x)-len(x)%n]).reset_index(drop=True)

Оба из них будут принимать начало данных каждой группы, вплоть до ближайшего кратного n.

Если вместо этого вы хотите случайные данные (вместо начала данных) для каждой группы, но чтобы размер каждой группы был кратным n, используйте sample вместо head / iloc:

df.groupby('ID').apply(lambda x: x.sample(len(x) - len(x) % n)).reset_index(drop=True)

   Time  ID  X_Pos  Y_Pos
0     2   1    160    310
1     1   1    150    300
2     4   2    300    439
3     5   2    200    500
4     9   3    450    600
5    10   3    400    600
6     8   3    500    540
7     6   3    500    320
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...