Pandas – Как извлечь значение в текущую строку на основе предыдущей строки

У меня есть фрейм данных pandas с именами столбцов Index, A, B, C, D. Значения в столбце D имеют либо положительные, либо отрицательные числа. Если, скажем, начальное значение индекса 0 для столбца D является отрицательным числом, то оно будет продолжаться таким же образом еще несколько строк, прежде чем переключиться на положительное число. Как только он переключится, он будет иметь тот же шаблон: в столбце D появится несколько положительных чисел, прежде чем он снова переключится на отрицательное.

Я хочу создать новый фрейм данных и сохранять в нем ссылку на индекс каждый раз, когда значения изменяются с положительного на отрицательное в столбце D или с отрицательного на положительное в столбце D. Следовательно, в приведенном ниже примере необходимо захватить индексы 3 и 7. :

Index  Col D
0      23.3
1      24.4
2      43
3     -45
4     -54
5     -56
6     -89
7      89
8      90
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
97
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Код

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

out = df[df['Col D'].mul(df['Col D'].shift()).lt(0)].index

вне:

Int64Index([3, 7], dtype='int64')

Пример кода

import pandas as pd
data = {'Col D': [23.3, 24.4, 43.0, -45.0, -54.0, -56.0, -89.0, 89.0, 90.0]}
df = pd.DataFrame(data)

дф

    Col D
0   23.3
1   24.4
2   43.0
3   -45.0
4   -54.0
5   -56.0
6   -89.0
7   89.0
8   90.0

Спасибо. Ваш код работает... однако я не совсем уверен, что понимаю, как он достигает результата. Могу ли я попросить вас дать краткое объяснение того, как связаны методы и как они работают в каждой строке без использования цикла for. Спасибо :)

Anushka A 16.04.2024 16:23

Вы можете использовать маску и дифф.

Если вы хотите считать 0 положительным числом:

s = df['Col D'].ge(0)
out = df.index[s.diff().fillna(False)]

Если вы хотите рассматривать 0 отдельно от отрицательного/положительного, сначала используйте numpy.sign:

import numpy as np

s = np.sign(df['Col D'])
out = df.index[s.diff().fillna(0).ne(0)]

Выход:

Index([3, 7], dtype='int64')
Промежуточные продукты

считая 0 положительным числом:

   Col D      s s.diff()  s.diff().fillna(False)
0      1   True      NaN                   False
1      2   True    False                   False
2     -1  False     True                    True
3     -2  False    False                   False
4      0   True     True                    True
5      1   True    False                   False  # 1 and 0 have the same sign

учитывая 0 независимо:

   Col D  s  s.diff()  s.diff().fillna(0).ne(0)
0      1  1       NaN                     False
1      2  1       0.0                     False
2     -1 -1      -2.0                      True
3     -2 -1       0.0                     False
4      0  0       1.0                      True
5      1  1       1.0                      True  # 1 and 0 have a different sign
Ответ принят как подходящий

Функция numpy.sign возвращает -1 if x < 0, 0 if x==0, 1 if x > 0. Абсолютная разница между возвращаемыми значениями между двумя строками при изменении знака равна 2. Используйте метод series.diff, чтобы найти, где это происходит.

import numpy as np
import pandas as pd

sample = {
    "D": [23.3, 24.4, 43, -45, -54, -56, -89, 89, 90]
}

df = pd.DataFrame(sample)

df.index[df.D.map(np.sign).diff().abs().eq(2)]

Выход:

Index([3, 7], dtype='int64')

Объяснение операций с данными:

  • df.D: выбирает столбец «D» из DataFrame df, что эквивалентно df["D"].

  • .map(np.sign): применяет функцию NumPy np.sign поэлементно к значениям в столбце «D». Функция np.sign возвращает -1 для отрицательных чисел, 0 для нуля и 1 для положительных чисел.

  • .diff(): вычисляет разницу между последовательными элементами ряда, полученными после применения np.sign к столбцу «D». Учитывая, что в столбце нет нулевого значения, возможными результатами являются -2 и 2 (Отрицательный -> Положительный: -1 - 1 = -2; Положительный -> Отрицательный: 1 - -1 =2)

  • .abs(): вычисляет абсолютное значение результирующей серии на основе .diff(). Этот шаг гарантирует, что все различия положительны, поэтому при изменении знака результат всегда равен 2.

  • .eq(2): Сравнивает каждый элемент результирующей серии с 2, возвращая логическую серию, где True указывает, что разница равна 2, а False в противном случае.

  • df.index[df.D.map(np.sign).diff().abs().eq(2)]: окончательное выражение использует логическое индексирование индекса DataFrame для извлечения индексов, в которых условие .eq(2) имеет значение True.

Означает ли это, что у [-1, 0, 1] не будет смены знака? ;)

mozway 14.04.2024 09:55

Да. В вопросе нет требования к 0.

Dan Nagle 14.04.2024 13:41

Спасибо, Дэн, за твой ответ. Это сработало. Если у вас есть минутка, могу ли я попросить вас объяснить методы, которые вы использовали для решения этой проблемы, и что они делают в этом контексте?

Anushka A 16.04.2024 16:49

Я обновил ответ, включив в него объяснение того, как работает код.

Dan Nagle 16.04.2024 17:17
import numpy as np
import pandas as pd


data = {'Index': [0, 1, 2, 3, 4, 5, 6, 7, 8],
        'Col D': [23.3, 24.4, 43, -45, -54, -56, -89, 89, 90]}
df = pd.DataFrame(data)
print(df)
# Convert Column D to a NumPy array
col_d_values = df['Col D'].to_numpy()#df['Col D'].values

# Find the sign of each value in Column D
signs = np.sign(col_d_values)
print(signs)#[ 1.  1.  1. -1. -1. -1. -1.  1.  1.]

# Find the indices where the sign changes
sign_changes = np.where(np.diff(signs) != 0)[0] + 1

# Get the index references where the sign changes
index_references = df.loc[sign_changes, 'Index'].tolist()

print(index_references)#[3, 7]

Другие вопросы по теме