В настоящее время я использую pandas для управления файлом CSV, содержащим данные о местонахождении судов на карте. У меня есть фрейм данных Pandas, который выглядит так (упрощенно):
C_p — коэффициент достоверности, позволяющий судить о том, припарковано ли судно.
Способ оценки припаркованного судна следующий:
Если среднее значение C_p последовательности данных выше 80
, эта последовательность данных является припаркованным судном, а минимальный номер последовательности выше 3
.
Таким образом, в этом примере индексы от 2 до 4 представляют собой последовательность припаркованных судов, поскольку среднее значение C_p составляет 82,67, что превышает 80. Несмотря на то, что индексы от 7 до 8, среднее значение C_p превышает 80, последовательность состоит всего из двух элементов. так что это не припаркованное судно.
Итак, я хочу получить это:
Я пытаюсь изменить этот метод на вопрос Leetcode, например:
for i in range(n - 2): # n is the element number of a group
avg = (C_p[i] + C_p[i+1] + C_p[i+2]) / 3
if avg >= 80:
is_parked[i] = is_parked[i+1] = is_parked[i+2] = 1 # default value of is_parked is 0
Но я понятия не имею, как реализовать это с помощью Pandas или Python.
Итак, мой вопрос:
Есть ли способ реализовать это в Pandas?
Если нет, следует ли мне обратиться к Numpy или к чему-то еще, чтобы получить результаты?
Обновлено: 1 Комментарий Ника позволяет мне перепроверить мой пример и мой метод.
Если C_p[5] = 78, это все еще припаркованное судно и оно рассчитывается для каждой группы.
Я не учел этого, поэтому моя первая попытка была неудачной. Вот моя новая попытка
for i in range(n):
thisSUM = C_p[i]
for j in range(i+1, n):
thisSUM += C_p[j]
avg = thisSUM / (j - i + 1)
if avg >= 80 and j - i + 1 >= 3:
for k in range(i, j+1):
is_parked_check[k] = 1
Временная сложность равна O(n^3), что нехорошо.
Кроме того, это должно рассчитываться индивидуально или на основе всех данных?
Моя попытка ошибочна. Если C_p[5] = 78, это все еще припаркованное судно и оно рассчитывается для каждой группы. Спасибо, что напомнили.
Вы можете использовать двойное перекатывание в groupby.transform. Первый — вычислить скользящее среднее, затем мы проверяем, превышает ли значение пороговое значение. Затем мы переворачиваем серию и вычисляем скользящий максимум, чтобы распространить значение True/1 на предыдущие строки N-1:
N = 3
threshold = 80
df['is_parked'] = (df.groupby('Group')['C_p']
.transform(
lambda s: s.rolling(N).mean().gt(threshold)[::-1]
.rolling(N, min_periods=1).max()
.astype(int)
)
)
Выход:
Index Group C_p is_parked
0 1 1 27 0
1 2 1 85 1
2 3 1 83 1
3 4 1 78 1
4 5 1 66 0
5 6 1 47 0
6 7 3 82 0
7 8 3 80 0
8 9 3 66 0
Промежуточные продукты:
Index Group C_p formula avg >80 rev_roll
0 1 1 27 NaN NaN False 0
1 2 1 85 NaN NaN False 1
2 3 1 83 (83+85+27)/3 65.000000 False 1
3 4 1 78 (78+83+85)/3 82.000000 True 1
4 5 1 66 (66+78+83)/3 75.666667 False 0
5 6 1 47 (47+66+78)/3 63.666667 False 0
6 7 3 82 NaN NaN False 0
7 8 3 80 NaN NaN False 0
8 9 3 66 (66+80+82)/3 76.000000 False 0
Спасибо, что просветили меня, но мой первый метод был неправильным. Я добавляю свой новый метод в недавнее редактирование.
@AndrewChao Я считаю, что мой код уже делает то, что вы хотите. Я добавил некоторые детали, пожалуйста, проверьте еще раз и уточните, если необходимо.
А что, если
C_p[5] = 78
? Это все еще припаркованное судно (поскольку последовательность из 2-5 имеет среднее значение >= 80) или не припарковано (поскольку последовательность из 3-5 имеет среднее значение <= 80)?