Объединить многострочные строки в фрейме данных pandas на основе шаблона регулярного выражения

У меня есть фрейм данных с одним столбцом, похожий на этот:

cat = { 'cat': ['a','b','c-','        -d','e']}
df = pd.DataFrame(cat)

>>> print(df)
          cat
0           a
1           b
2          c-
3          -d
4           e

Мне нужно объединить строки 2 и 3:

          cat
0           a
1           b
2          cd
3          e

Я пытаюсь использовать регулярное выражение, поскольку эти многострочные данные всегда имеют вид «-\n {8}-». Однако это не работает:

df['cat'] = df['cat'].str.replace("-\n {8}-","",flags=re.M)

Я не могу использовать какие-либо методы группировки, поэтому я как бы застрял. Спасибо за любые предложения.

всегда ли поля, подлежащие объединению, находятся рядом друг с другом?

Chris 26.08.2024 22:10
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
53
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете использовать подход groupby, определив строки, которые заканчиваются на - или начинаются на {8}-:

m1 = df['cat'].str.endswith('-')
m2 = df['cat'].str.match(' {8}-')
group = (~(m1.shift(fill_value=False) & m2)).cumsum().rename()

out = (df['cat'].groupby(group)
       .agg(lambda x: ''.join(x).replace('-        -', ''))
       .to_frame()
      )

Выход:

  cat
1   a
2   b
3  cd
4   e

Промежуточные продукты:

          cat     m1     m2  group
0           a  False  False      1
1           b  False  False      2
2          c-   True  False      3
3          -d  False   True      3
4           e  False  False      4

Или без панд, join все строки со специальным разделителем (например, \n, замените затем split еще раз):

import re

out = pd.DataFrame({'col': re.sub(r'-\n {8}-', '', '\n'.join(df['cat']))
                             .split('\n')})

Выход:

  col
0   a
1   b
2  cd
3   e

Второе, более простое решение сработало очень хорошо, спасибо!

eazyezy 26.08.2024 22:47

Я бы сделал это так:

  1. Объединение сдвинутых на одну/несмещенных «кошачьих» строк
  2. Найдите свой шаблон регулярного выражения во вновь созданных значениях.
  3. Фильтровать/обновлять фрейм данных
  4. Замените многострочные значения пустой строкой
tmp = df["cat"].shift() + df["cat"]
m = tmp.str.contains(r"-\s{8,}-").eq(True)

df = df[~m.shift(-1).eq(True)]
df.update(tmp[m])

df["cat"] = df["cat"].str.replace(r"-\s{8,}-", "", regex=True)

print(df)

Распечатки:

  cat
0   a
1   b
3  cd
4   e

Другое возможное решение, основанное на следующих шагах:

  1. Он обновляет значение в ячейке с индексом строки n и столбца cat. Это новое значение рассчитывается путем добавления текущего значения в cat к значению в следующей строке (n+1) столбца cat с использованием пустой строки для заполнения всех пропущенных значений. Затем результат очищается путем удаления всех вхождений шаблона '-\n {8}-', а значение из индекса строки n этой очищенной серии присваивается обратно df.loc[n, 'cat'].

  2. Затем он удаляет строку с индексом n+1 из кадра данных и сбрасывает индекс, чтобы гарантировать его непрерывность, отбрасывая старый индекс.

n = 2

df.loc[n, 'cat'] = (df['cat'].add(df['cat'].shift(-1), fill_value='')
                    .str.replace(r'-\n {8}-', '', regex=True).iloc[n])
df.drop(df.index[n+1]).reset_index(drop=True)

Выход:

  cat
0   a
1   b
2  cd
3   e

Другие вопросы по теме