Цикл и массивы строк в питоне - PullRequest
0 голосов
/ 12 октября 2018

У меня есть следующий набор данных:

column1

HL111
PG3939HL11
HL339PG
RC--HL--PG

Я пытаюсь написать функцию, которая выполняет следующее:

  1. Цикл по каждой строке столбца1
  2. Потяните только алфавит и поместите в массив
  3. Если в массиве есть "HL", удалите его из массива, ЕСЛИ НЕ HL является единственным словом в массиве.
  4. Возьмитепервое слово в массиве и вывод результатов.

Итак, для приведенного выше примера мой массив (шаг2) будет выглядеть так:

[HL]
[PG,HL]
[HL,PG]
[RC,HL,PG]

и мой желаемый конечный результат (шаг4)) будет выглядеть так:

desired_column

HL
PG
PG
RC

У меня есть код для шага 2, и он, кажется, работает нормально

df['array_column'] = (df.column1.str.extractall('([A-Z]+)')
                    .unstack()
                    .values.tolist())

Но я не знаю, как добраться отсюда домой окончательный вывод (шаг4).

Ответы [ 3 ]

0 голосов
/ 12 октября 2018

Вы можете достичь того, что вам нужно, сначала заменив все не-буквы, затем выделив пары букв, а затем применив некоторую пользовательскую логику для извлечения необходимого значения из массива:

>>> df['array_column'].str.replace('[^A-Z]+', '').str.findall('([A-Z]{2})').apply(lambda d: [''] if len(d) == 0 else d).apply(lambda x: 'HL' if len(x) == 1 and x[0] == 'HL' else [m for m in x if m != 'HL'][0])
0    HL
1    PG
2    PG
3    RC
Name: array_column, dtype: object
>>> 

Подробности

  • .replace('[^A-Z]+', '') - удалить все символы, кроме заглавных букв
  • .str.findall('([A-Z]{2})') - извлечь пары букв
  • .apply(lambda d: [''] if len(d) == 0 else d) добавит пустойitem, если на предыдущем шаге нет соответствия регулярному выражению
  • .apply(lambda x: 'HL' if len(x) == 1 and x[0] == 'HL' else [m for m in x if m != 'HL'][0]) - пользовательская логика: если длина списка равна 1 и равна HL, сохраните ее, в противном случае удалите все HL и получитепервый элемент
0 голосов
/ 12 октября 2018

Вы можете сделать что-то вроде этого (или, возможно, что-то более элегантное), то, что у вас уже есть, приведет вас к довольно приятной структуре, где вы можете использовать groupby для завершения вашего решения

def extract_relevant_str(grp):
    ret_val = None
    if "HL" in grp[0].tolist() and len(grp) == 1:
        ret_val = "HL"
    elif len(grp) >= 1:
        ret_val = grp.loc[grp[0] != "HL", 0].iloc[0]
    return ret_val

items = df.column1.str.extractall('([A-Z]+)')
items.reset_index().groupby("level_0").apply(extract_relevant_str)

Вывод:

level_0
0    HL
1    PG
2    PG
3    RC
dtype: object
0 голосов
/ 12 октября 2018

Это один подход с использованием apply

Демонстрация:

import re
import pandas as pd

def checkValue(value):
    value = re.findall(r"[A-Z]{2}", value)
    if (len(value) > 1) and ("HL" in value):
        return [i for i in value if i != "HL"][0]
    else:
        return value[0]    

df = pd.DataFrame({"column1": ["HL111", "PG3939HL11", "HL339PG", "RC--HL--PG"]})
print(df.column1.apply(checkValue))

Вывод:

0    HL
1    PG
2    PG
3    RC
Name: column1, dtype: object
...