Извлечение тома из серии pandas - Pandas, Regex - PullRequest
4 голосов
/ 05 апреля 2020

У меня есть серия Pandas, которую можно получить с помощью следующего кода:


Ввод:

l = ['abcd 1942 Lmauu 40% 70cl',
    'something again something   1.5 L',
    'some other stuff 45% 70 CL',
    'not the exact data      3LTR',
    'abcd 100Ltud 6%(8)500ML',
    'cdef  6%(8)500 ml',
    'a packet 24 x 27.5 cl (  PET )']
ser = pd.Series(l)

Постановка проблемы и ожидаемый результат:

Я пытаюсь извлечь тома из ряда и преобразовать их в кадр данных таким образом, чтобы объем находился в 1 столбце кадра данных, а единица измерения в другой столбец, ожидаемый результат может быть воспроизведен с использованием приведенного ниже кода:

d = {0: {0: '70',
     1: '1.5',
     2: '70',
     3: '3',
     4: '500',
     5: '500',
     6: '27.5'},
     1: {0: 'cl', 1: 'L', 2: 'CL', 3: 'LTR', 4: 'ML', 5: 'ml', 6: 'cl'}}
expected_output = pd.DataFrame(d)

      0    1
0    70   cl
1   1.5    L
2    70   CL
3     3  LTR
4   500   ML
5   500   ml
6  27.5   cl 

Мой пробный код

Вот что я пробовал, я пришел очень близко к тому, что я хочу, но не совсем, если вы видите, я не получаю последний том. Я думаю, потому что я включил $ в свое регулярное выражение, но без него я не смог бы проанализировать объем, как в этой строке, например, abcd 1942 Lmauu 40% 70cl, 1942 L были бы возвращены. Также мне нужна единица измерения только во втором столбце, а не в первом, как показано в моих выходных данных, но это вторично.

print(ser.str.extract(r'((?i)([\d]+?[.])?\d+?[\s+]?(cl$|ml$|ltr$|L$)(?:$))').iloc[:,[0,-1]]) 

        0    2
0    70cl   cl
1   1.5 L    L
2   70 CL   CL
3    3LTR  LTR
4   500ML   ML
5  500 ml   ml
6     NaN  NaN 

Пожалуйста, предложите, что мне делать здесь.

Ответы [ 2 ]

2 голосов
/ 05 апреля 2020

Вы можете использовать

r'(?i)\b(\d+(?:\.\d+)?)\s*(cl|ml|ltr|L)\b'

См. Демоверсию regex .

Подробности

  • (?i) - режим нечувствителен к регистру
  • \b - граница слова
  • (\d+(?:\.\d+)?) - Группа захвата 1: одна или несколько цифр, за которыми следует необязательная последовательность точки и одна или несколько цифр
  • \s* - 0+ пробелов
  • (cl|ml|ltr|L) - cl, ml, ltr или L (учитывайте регистр без учета регистра)
  • \b - граница слова

Тест:

>>> ser.str.extract(r'(?i)\b(\d+(?:\.\d+)?)\s*(cl|ml|ltr|L)\b', expand=True)
      0    1
0  70    cl 
1  1.5   L  
2  70    CL 
3  3     LTR
4  500   ML 
5  500   ml 
6  27.5  cl
1 голос
/ 05 апреля 2020

Лучше использовать именованные группы захвата, чтобы столбцы результатов имели значимые имена.

Я также немного упростил ваше регулярное выражение и изменил единицы измерения на строчные.

Поэтому измените свой код на:

res = ser.str.extract(r'(?i)(?P<Amount>\d+(?:\.\d+)?)\s?(?P<Unit>[CM]?L|LTR)\b')
res.Unit = res.Unit.str.lower()

Результат:

  Amount Unit
0     70   cl
1    1.5    l
2     70   cl
3      3  ltr
4    500   ml
5    500   ml
6   27.5   cl

Обратите внимание, что $ in (cl $ | ml $ | ltr $ | L $) неверно, потому что по крайней мере в одном случае у вас есть дополнительный текст после единицы измерения.

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