Как условно сгруппировать данные на основе значений в кадре данных? - PullRequest
0 голосов
/ 13 июня 2019

У меня есть следующий упорядоченный фрейм данных, который имеет положение определенных строк в текстовом файле

data:

index position 
  0     125
  1     256
  2     314
  3     355
  4     549
  5     601
  6     654
  7     727
  8     1100
  9     1217

У меня есть другой фрейм данных, в котором есть сообщения msg1, msg2 и msg3с их положением в текстовом файле и может иметь несколько экземпляров.Эти сообщения показывают, как группировать данные

сообщение:

index position  message 
  0     210     msg1
  1     313     msg2
  2     525     msg3
  3     575     msg2
  4     632     msg1
  5     731     msg3

Условия

a), если строка предшествует первому обнаруженному сообщению (не обязательно msg1, идентифицированному по позиции) тогда строка будет классифицироваться как оценка A

b) если строка идет после последнего сообщения (не обязательно msg3, идентифицированного позицией), то строка будет классифицироваться как:

a) if msg1 is last: grade A1

b) if msg2 is last: grade A2

c) if msg3 is last: grade A3

c) если строка находится между двумя сообщениями, то есть началом msg [i] и концом msg [j], тогда строка будет классифицироваться как 'класс A' + str (i)

Я пробовал операторы if elseи не удалось реализовать это правильно.Будет признателен любой более простой способ сделать это без какого-либо жесткого кодирования позиций в кадре сообщения.

Ожидаемый результат - панда серии / dataframe или список со строками, сгруппированными согласно условию

index position  group
  0     125    grade A
  1     256    grade A1
  2     314    grade A2
  3     355    grade A2
  4     549    grade A3
  5     601    grade A2
  6     654    grade A1
  7     727    grade A1
  8     1100   grade A3
  9     1217   grade A3

Ответы [ 2 ]

0 голосов
/ 13 июня 2019

Я бы:

  • согласовать оба кадра данных
  • добавить новый столбец grade для всех строк, в которых сообщение вычислено как 'grade A' + номер сообщения
  • сортировать объединенный фрейм данных в столбце position
  • используйте fillna, чтобы заполнить столбец оценки оценкой предыдущего сообщения
  • снова используйте fillna, чтобы установить любую строку перед первым сообщением на 'grade A'
  • извлечение строк без сообщения для построения результирующего кадра данных

Код может быть:

tmp = pd.concat([df1,df2], sort=False).sort_values(
    ['position'])

tmp.loc[~tmp['message'].isna(),'grade'] = 'grade A' + tmp.loc[
    ~tmp['message'].isna(),'message'].str[3]

tmp['grade']=tmp['grade'].fillna(method='ffill').fillna('grade A')

resul = tmp.loc[tmp.message.isna()].drop(columns=['message'])

С вашими данными выборки, вы получите, как и ожидалось:

index  position     grade
    0       125   grade A
    1       256  grade A1
    2       314  grade A2
    3       355  grade A2
    4       549  grade A3
    5       601  grade A2
    6       654  grade A1
    7       727  grade A1
    8      1100  grade A3
    9      1217  grade A3
0 голосов
/ 13 июня 2019

Для каждой строки в фрейме данных сообщений мы добавляем позицию следующего сообщения для удобства сравнения:

messages = messages.join(messages['position'].shift(-1).rename('next_position'))

Добавить сообщение для каждой строки в данных:

data['class'] = 0
for index, row in messages.iterrows():
  data.loc[data['position'].between(row['position'],row['next_position']),'class'] = row['message']

Добавьте «крайние» случаи:

data.loc[data['position'].between(0,messages['position'].min()),'class'] = 'msg'
data.loc[data['position'].between(messages['position'].max(),np.inf),'class'] = messages.iloc[-1]['message']

И замените сообщения вашим классом

for message_code in data['class'].unique():
    data.replace(message_code,'A'+message_code.split('msg')[-1],inplace=True)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...