У меня есть фрейм данных с одним столбцом, похожий на этот:
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)
Я не могу использовать какие-либо методы группировки, поэтому я как бы застрял. Спасибо за любые предложения.
🤔 А знаете ли вы, что...
Python поддерживает множество парадигм программирования, включая процедурное, объектно-ориентированное и функциональное программирование.
Вы можете использовать подход 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
Я бы сделал это так:
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
Другое возможное решение, основанное на следующих шагах:
Он обновляет значение в ячейке с индексом строки n
и столбца cat
. Это новое значение рассчитывается путем добавления текущего значения в cat
к значению в следующей строке (n+1
) столбца cat
с использованием пустой строки для заполнения всех пропущенных значений. Затем результат очищается путем удаления всех вхождений шаблона '-\n {8}-'
, а значение из индекса строки n
этой очищенной серии присваивается обратно df.loc[n, 'cat']
.
Затем он удаляет строку с индексом 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