< Сильный > UPDATE

У меня есть следующий набор данных, и я хочу получить список, который включает в себя три последних индекса перед меткой «ДА». Мой набор данных:

i            category
0               NO
1               NO
2               NO
3               NO
4               NO
5               YES
6               YES
7               YES
8               NO
9               NO
10              NO
11              YES
12              YES

Я ожидаю, что результат будет:

Список = [ 2,3,4,8,9,10 ]

Обратите внимание, что ДА обычно происходят в последовательном диапазоне образцов (2-6 образцов). Я хочу получить последние три индекса перед первым ДА в диапазоне.

P.S: набор данных был сохранен в файле CSV, и я импортировал с помощью панд

1
Alex Davies 23 Июн 2019 в 23:01

3 ответа

Лучший ответ

Вероятно, не самый питонический способ, но я не мог придумать, как сделать это без цикла for и некоторой нарезки, похоже на хакерский метод:

a = df[((df.category.ne(df.category.shift()))==True) & (df.category == 'YES')].index


indices = []
for x in a:
    indices.append(df.iloc[slice(max(0, x-3), min(x, len(df)))])
new_df = pd.concat(indices) # if you wanted this as a df.

list(new_df.index)


[2, 3, 4, 8, 9, 10]
2
Datanovice 23 Июн 2019 в 21:58

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

Второй цикл for - просто сгладить двойной список из списка результатов.

li= ['1','2','3','4','YES','6','7','8','9','0','YES']
result = []
for x in range(len(li)):
  if li[x] is 'YES':
    result.append(li[x-3:x])


final= []
for x in result:
  for y in x:
    final.append(y)

Final = ['2', '3', '4', '8', '9', '0']

1
Kellen Mills 23 Июн 2019 в 21:03

Предположим, как вы указали в своем комментарии, что перед каждым ДА всегда есть как минимум 3 пункта. Возможное решение будет

import pandas as pd

flatten = lambda l: [item for sublist in l for item in sublist]

df = pd.DataFrame({"category":['NO', 'NO', 'NO', 'NO', 'NO',
                               'YES', 'NO', 'NO', 'NO', 'NO',
                               'NO','YES','NO']})
# take only indices where YES occurs
idx = df[df["category"]=="YES"].index

# for every i in idx take the previuos 3 indices
lst = [list(range(i-3, i)) for i in idx]

# flatten lst
lst = flatten(lst)
1
rpanai 23 Июн 2019 в 20:39