Несколько операций .shift () перезаписывают друг друга - PullRequest
0 голосов
/ 07 июня 2018

Можно ли применить сдвиг только к определенному подмножеству кадра данных?В настоящее время ниже будет перезаписывать df ['End'], потому что я назначаю его непосредственно df ['End'], но я не могу понять, как применить его только к меньшему выделению.

По существу яиметь данные с одним столбцом даты, а дата окончания - это дата начала следующих строк, но только если она определенного типа.В последней строке должен использоваться только один и тот же начало / конец.

Откройте для любых других идей, как это сделать также!

Пример данных

Start   Field
2018-05-22T19:03:30+0000    Product
2018-05-22T19:09:30+0000    Size
2018-05-22T19:09:30+0000    Category
2018-05-22T19:25:39+0000    Product
2018-05-22T19:42:41+0000    Size
2018-05-22T20:57:30+0000    Category

# First Shift
df['End'] = df.loc[df['Field'].isin(['Product', 'Category'])]['Start'].shift(periods=-1)

# Update last row  
shift_rows = df.loc[df['Field'].isin(['Product', 'Category'])]
df.iloc[-1, shift_rows.columns.get_loc('End')] = shift_rows.iloc[-1, df.columns.get_loc('Start')] 

# Second shift        
df['End'] = df.loc[df['Field'].isin(['Size'])['Start'].shift(periods=-1)

# Update last row
shift_rows = df.loc[df['Field'].isin(['Size'])]
df.iloc[-1, shift_rows.columns.get_loc('End')] = shift_rows.iloc[-1, df.columns.get_loc('Start')]

Ожидаемый результат

Start   Field   End
2018-05-22T19:03:30+0000    Product 2018-05-22T19:09:30+0000
2018-05-22T19:09:30+0000    Size    2018-05-22T19:42:41+0000
2018-05-22T19:09:30+0000    Category    2018-05-22T19:25:39+0000
2018-05-22T19:25:39+0000    Product 2018-05-22T20:57:30+0000
2018-05-22T19:42:41+0000    Size    2018-05-22T19:42:41+0000
2018-05-22T20:57:30+0000    Category    2018-05-22T20:57:30+0000

1 Ответ

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

Одной из идей может быть создание столбца Field_group, имеющего номер для другой группы полей.С вашим примером:

df['Field_group'] = df['Field'].apply(lambda field: 1 if field in ['Product', 'Category'] else 2)

Если у вас более 2 групп полей, вы можете что-то вроде:

def associate_group_number (field):
    if field in ['Product', 'Category']: return 1
    if field in ['Size','blabla']: return 2
    if field in ['blo','bli','blu']: return 3
df['Field_group'] = df['Field'].apply(associate_group_number)

Теперь, когда у вас есть номер группы, вы можете использовать groupbyи shift для создания столбца «Конец», например:

df['End'] = df.groupby('Field_group')['Start'].shift(-1)

И поскольку вы хотите заполнить последнюю строку End каждой группы временем, соответствующим этой строке в Start(если я хорошо понял), вы можете использовать fillna:

df['End'] = df['End'].fillna(df['Start'])

Вы можете даже добавить .fillna(df['Start']) после shift(-1) предыдущей строки кода, чтобы сделать это в одну строку, это работает(здесь это должно было быть объяснено)

Наконец, вы можете удалить столбец, созданный с помощью:

df = df.drop('Field_group',1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...