Я хочу найти начальный и конечный индексы каждого фрагмента данных в наборе данных. Данные как:
index A wanted_column1 wanted_column2
2000/1/1 0 0
2000/1/2 1 2000/1/2 1
2000/1/3 1 1
2000/1/4 1 1
2000/1/5 0 0
2000/1/6 1 2000/1/6 2
2000/1/7 1 2
2000/1/8 1 2
2000/1/9 0 0
Как показано в данных, index
и A
- это заданные столбцы, а wanted_column1
и wanted_column2
- то, что я хочу получить. Идея состоит в том, что есть разные части непрерывных кусков данных. Я хочу получить начальные индексы для каждого фрагмента данных и увеличить счетчик количества фрагментов в данных.
Я пытался использовать shift(-1)
, но невозможно shift(-1)
разницу между начальным индексом и конечным индексом.
Предполагая, что ваш фрейм данных равен df
, вы можете найти индексы, где df['A'] != 0
. Предыдущие индексы - это последние индексы чанка, после первых - чанка. Позже вы посчитаете количество найденных индексов, чтобы рассчитать количество порций данных
import pandas as pd
# Read your data
df = pd.read_csv('my_txt.txt', sep=',')
df['wanted_column1'] = None # creating already dummy columns
df['wanted_column2'] = None
# Find indices after each index, where 'A' is not 1, except of it is the last value
# of the dataframe
first = [x + 1 for x in df[df['A'] != 1].index.values if x != len(df)-1]
# Find indices before each index, where 'A' is not 1, except of it is the first value
# of the dataframe
last = [x - 1 for x in df[df['A'] != 1].index.values if x != 0]
# Set the first indices of each chunk at its corresponding position in your dataframe
df.loc[first, 'wanted_column1'] = df.loc[first, 'index']
# You can set also the last indices of each chunk (you only mentioned this in the text,
# not in your expected-result-listed). Uncomment for last indices.
# df.loc[last, 'wanted_column1'] = df.loc[last, 'index']
# Count the number of chunks and fill it to wanted_column2
for i in df.index: df.loc[i, 'wanted_column2'] = sum(df.loc[:i, 'wanted_column1'].notna())
# Some polishing of the df after to match your expected result
df.loc[df['A'] != 1, 'wanted_column2'] = 0
Это дает
index A wanted_column1 wanted_column2
0 2000/1/1 0 None 0
1 2000/1/2 1 2000/1/2 1
2 2000/1/3 1 None 1
3 2000/1/4 1 None 1
4 2000/1/5 0 None 0
5 2000/1/6 1 2000/1/6 2
6 2000/1/7 1 None 2
7 2000/1/8 1 None 2
8 2000/1/9 0 None 0
и работает для всех длин df
и количества кусков в ваших данных
Это то, что вам нужно?
df['change'] = df['A'].diff().eq(1)
df['wanted_column1'] = df[['index','change']].apply(lambda x: x[0] if x[1] else None, axis=1)
df['wanted_column2'] = df['change'].cumsum()
df['wanted_column2'] = df[['wanted_column2','A']].apply(lambda x: 0 if x[1]==0 else x[0], axis=1)
df.drop('change', axis=1, inplace=True)
Это дает:
index A wanted_column1 wanted_column2
0 2000/1/1 0 None 0
1 2000/1/2 1 2000/1/2 1
2 2000/1/3 1 None 1
3 2000/1/4 1 None 1
4 2000/1/5 0 None 0
5 2000/1/6 1 2000/1/6 2
6 2000/1/7 1 None 2
7 2000/1/8 1 None 2
8 2000/1/9 0 None 2
Изменение: сравнение производительности
gehbiszumeis
: 19.9 ms
my
решение: 4.07 ms
IIUC вам нужно что-то вроде ниже:
import itertools
v = df.index[df.index.isin(list(itertools.chain.from_iterable([df[df.A==0].index+1])))]
df['index'].loc[v]
Выход
1 2000-01-02
5 2000-01-06