Phiên bản TL; DR:
Đối với trường hợp đơn giản là:
- Tôi có một cột văn bản với một dấu phân cách và tôi muốn hai cột
Giải pháp đơn giản nhất là:
df['A'], df['B'] = df['AB'].str.split(' ', 1).str
Hoặc bạn có thể tạo một DataFrame với một cột cho mỗi mục phân chia tự động với:
df['AB'].str.split(' ', 1, expand=True)
Bạn phải sử dụng expand=True
nếu chuỗi của bạn có số lần phân tách không đồng nhất và bạn muốn None
thay thế các giá trị bị thiếu.
Lưu ý làm thế nào, trong cả hai trường hợp, .tolist()
phương pháp là không cần thiết. Cũng không zip()
.
Chi tiết:
Giải pháp của Andy Hayden là tuyệt vời nhất trong việc chứng minh sức mạnh của str.extract()
phương pháp.
Nhưng đối với một phân tách đơn giản trên một dấu phân cách đã biết (như, phân tách bằng dấu gạch ngang hoặc phân tách bằng khoảng trắng), .str.split()
phương thức này là đủ 1 . Nó hoạt động trên một cột (Sê-ri) chuỗi và trả về một cột (Sê-ri) danh sách:
>>> 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: Nếu bạn không chắc chắn hai tham số đầu tiên .str.split()
phải làm gì, tôi khuyên bạn nên sử dụng tài liệu cho phiên bản Python đơn giản của phương thức .
Nhưng làm thế nào để bạn đi từ:
- một cột chứa danh sách hai yếu tố
đến:
- Hai cột, mỗi cột chứa phần tử tương ứng của danh sách?
Chà, chúng ta cần xem xét kỹ hơn .str
thuộc tính của một cột.
Đó là một đối tượng ma thuật được sử dụng để thu thập các phương thức coi mỗi phần tử trong một cột thành một chuỗi, sau đó áp dụng phương thức tương ứng trong mỗi phần tử một cách hiệu quả nhất có thể:
>>> 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
Nhưng nó cũng có giao diện "lập chỉ mục" để lấy từng phần tử của chuỗi theo chỉ mục của nó:
>>> df['AB'].str[0]
0 A
1 A
Name: AB, dtype: object
>>> df['AB'].str[1]
0 1
1 2
Name: AB, dtype: object
Tất nhiên, giao diện lập chỉ mục .str
này không thực sự quan tâm nếu mỗi phần tử mà nó lập chỉ mục thực sự là một chuỗi, miễn là nó có thể được lập chỉ mục, vì vậy:
>>> 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
Sau đó, đó là một vấn đề đơn giản để tận dụng lợi thế của bộ giải nén Python để giải nén iterables để làm
>>> 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
Tất nhiên, việc lấy DataFrame ra khỏi việc tách một cột chuỗi rất hữu ích để .str.split()
phương thức có thể làm điều đó cho bạn với expand=True
tham số:
>>> df['AB'].str.split('-', 1, expand=True)
0 1
0 A1 B1
1 A2 B2
Vì vậy, một cách khác để thực hiện những gì chúng ta muốn là làm:
>>> 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
Các expand=True
phiên bản, mặc dù lâu hơn, có lợi thế rõ rệt so với tuple giải nén phương pháp. Tuple giải nén không giải quyết tốt với các phần tách có độ dài khác nhau:
>>> 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
>>>
Nhưng expand=True
xử lý nó một cách độc đáo bằng cách đặt None
vào các cột không có đủ "phần tách":
>>> 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()
hoặcread_fwf()