Версія TL; DR:
Для простого випадку:
- У мене є текстовий стовпчик з роздільником, і я хочу два стовпчики
Найпростіше рішення:
df['A'], df['B'] = df['AB'].str.split(' ', 1).str
Або ви можете створити DataFrame з одним стовпцем для кожного запису розділення автоматично за допомогою:
df['AB'].str.split(' ', 1, expand=True)
Ви повинні використовувати, expand=True
якщо у ваших рядків є неоднакова кількість розщеплень і ви хочете None
замінити відсутні значення.
Зауважте, як в будь-якому випадку .tolist()
метод не є необхідним. Ніzip()
.
Детально:
Рішення Енді Хейдена найкраще демонструє силу str.extract()
методу.
Але для простого розколу на відомий роздільник (наприклад, розбиття тире або розбиття пробілом) .str.split()
методу достатньо 1 . Він працює над стовпцем (Серією) рядків і повертає стовпець (Серія) списків:
>>> import pandas as pd
>>> df = pd.DataFrame({'AB': ['A1-B1', 'A2-B2']})
>>> df
AB
0 A1-B1
1 A2-B2
>>> df['AB_split'] = df['AB'].str.split('-')
>>> df
AB AB_split
0 A1-B1 [A1, B1]
1 A2-B2 [A2, B2]
1: Якщо ви не впевнені, що робити перші два параметри .str.split()
, я рекомендую документи для простої версії методу Python .
Але як походити:
- стовпчик, що містить двоелементні списки
до:
- два стовпці, кожен з яких містить відповідний елемент списків?
Що ж, нам потрібно уважніше подивитися .str
атрибут стовпця.
Це магічний об'єкт, який використовується для збору методів, які розглядають кожен елемент у стовпці як рядок, а потім застосовують відповідний метод до кожного елемента максимально ефективно:
>>> upper_lower_df = pd.DataFrame({"U": ["A", "B", "C"]})
>>> upper_lower_df
U
0 A
1 B
2 C
>>> upper_lower_df["L"] = upper_lower_df["U"].str.lower()
>>> upper_lower_df
U L
0 A a
1 B b
2 C c
Але він також має "індексування" інтерфейс для отримання кожного елемента рядка за його індексом:
>>> df['AB'].str[0]
0 A
1 A
Name: AB, dtype: object
>>> df['AB'].str[1]
0 1
1 2
Name: AB, dtype: object
Звичайно, цей інтерфейс індексування .str
насправді не хвилює, чи кожен елемент його індексації насправді є рядком, якщо він може бути індексований, так що:
>>> df['AB'].str.split('-', 1).str[0]
0 A1
1 A2
Name: AB, dtype: object
>>> df['AB'].str.split('-', 1).str[1]
0 B1
1 B2
Name: AB, dtype: object
Тоді, це просте питання скористатись кортежем Python для розпакування ітерабелів
>>> df['A'], df['B'] = df['AB'].str.split('-', 1).str
>>> df
AB AB_split A B
0 A1-B1 [A1, B1] A1 B1
1 A2-B2 [A2, B2] A2 B2
Звичайно, виведення DataFrame з розбиття стовпця рядків настільки корисно, що .str.split()
метод може зробити це для вас за допомогою expand=True
параметра:
>>> df['AB'].str.split('-', 1, expand=True)
0 1
0 A1 B1
1 A2 B2
Отже, ще один спосіб здійснити те, що ми хотіли:
>>> df = df[['AB']]
>>> df
AB
0 A1-B1
1 A2-B2
>>> df.join(df['AB'].str.split('-', 1, expand=True).rename(columns={0:'A', 1:'B'}))
AB A B
0 A1-B1 A1 B1
1 A2-B2 A2 B2
expand=True
Версія, хоча і довше, має явну перевагу по порівнянні з методом кортежу розпакування. Розпакування кортежу не дуже добре справляється з розколами різної довжини:
>>> df = pd.DataFrame({'AB': ['A1-B1', 'A2-B2', 'A3-B3-C3']})
>>> df
AB
0 A1-B1
1 A2-B2
2 A3-B3-C3
>>> df['A'], df['B'], df['C'] = df['AB'].str.split('-')
Traceback (most recent call last):
[...]
ValueError: Length of values does not match length of index
>>>
Але expand=True
це добре обробляє, розміщуючи None
в стовпцях, для яких недостатньо "розщеплення":
>>> df.join(
... df['AB'].str.split('-', expand=True).rename(
... columns={0:'A', 1:'B', 2:'C'}
... )
... )
AB A B C
0 A1-B1 A1 B1 None
1 A2-B2 A2 B2 None
2 A3-B3-C3 A3 B3 C3
read_table()
абоread_fwf()