Я не был уверен, что это лучший титул для этого, если у кого-то есть лучшая идея для титула, я готов к советам.
Скажем, у меня есть кадр данных, который выглядит так:
df2
A section
0 <fruit>
1 apple
2 orange
3 pear
4 watermelon
5 </fruit>
6 <furniture>
7 chair
8 sofa
9 table
10 desk
11 </furniture>
То, что я хочу, это dataframe, который выглядит так:
A section
0 <fruit> fruit
1 apple fruit
2 orange fruit
3 pear fruit
4 watermelon fruit
5 </fruit> fruit
6 <furniture> furniture
7 chair furniture
8 sofa furniture
9 table furniture
10 desk furniture
11 </furniture> furniture
Есть ли способ сделать это? Я думал об использовании инструкции if, чтобы идти по строке, но у меня были проблемы с логической логикой, когда я это делал.
Редактировать # 1:
Это решение, опубликованное ниже, решает мою проблему.
Решение:
df['section']=pd.Series(np.where(df.A.str.contains('<'),df.A.str.replace('<|>|/',''),np.nan)).ffill()
Что делать, если у меня есть данные, которые выглядят так? Я хотел бы получить тот же результат.
A section
0 <fruit>
1 <fruit_1>apple</fruit_1>
2 <fruit_2>orange</fruit_2>
3 <fruit_3>pear</fruit_3>
4 <fruit_4>watermelon</fruit_4>
5 </fruit>
6 <furniture>
7 <furniture_1>chair</furniture_1>
8 <furniture_2>sofa</furniture_2>
9 <furniture_3>table</furniture_3>
10 <furniture_4>desk</furniture_4>
11 </furniture>
Использование IIUC contains
поиск строки, а np.where
присваивает значение, затем используя ffill
fill np.nan
df['section']=pd.Series(np.where(df.A.str.contains('<'),df.A.str.replace('<|>|/',''),np.nan)).ffill()
df
Out[1003]:
A section
0 <fruit> fruit
1 apple fruit
2 orange fruit
3 pear fruit
4 watermelon fruit
5 </fruit> fruit
6 <furniture> furniture
7 chair furniture
8 sofa furniture
9 table furniture
10 desk furniture
11 </furniture> furniture
Если вы хотите быть более точным/конкретным/строгим, вы также можете проверить начало и конец строки, используя startswith
и endswith
.
df1['Section'] = pd.Series(np.where(df1.A.str.startswith('<') & df1.A.str.endswith('>'), df1.A.str.replace('<|>|/',''), np.nan)).ffill()
Я бы выбрал явное
import re
def parse_funky_xml(s):
tag = None
for x in s:
if tag is None:
match = re.match('<([^/]+)>', x)
if match:
tag = match.groups()[0]
yield tag
else:
match = re.match(f'</{tag}>', x)
yield tag
if match:
tag = None
df.assign(section=[*parse_funky_xml(df.A)])
A section
0 <fruit> fruit
1 apple fruit
2 orange fruit
3 pear fruit
4 watermelon fruit
5 </fruit> fruit
6 <furniture> furniture
7 chair furniture
8 sofa furniture
9 table furniture
10 desk furniture
11 </furniture> furniture