TL; Версия DR:
Для простого случая:
- У меня есть текстовый столбец с разделителем, и мне нужны два столбца
Самое простое решение:
df[['A', 'B']] = df['AB'].str.split(' ', 1, expand=True)
Вы должны использовать expand=True
, если ваши строки имеют неоднородное количество разбиений и вы хотите None
заменить отсутствующие значения.
Обратите внимание, что в любом случае метод .tolist()
не нужен. Ни zip()
.
В деталях:
Решение Энди Хайдена лучше всего демонстрирует возможности _ 6_.
Но для простого разделения по известному разделителю (например, разделение тире или разделение пробелами) _ 7_ достаточно 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.
Но как выйти из:
- столбец, содержащий двухэлементные списки
to:
- два столбца, каждый из которых содержит соответствующий элемент списков?
Что ж, нам нужно внимательнее взглянуть на атрибут .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
06.09.2016
index = df.index
, и все будет хорошо. 27.03.2013split
возвращает NaN, а методtolist
вернет это значение как есть (NaN), что приведет кValueError
(для решения этой проблемы вы можете преобразовать его в строковый тип перед разделением). Я рекомендую вам попробовать это самостоятельно, это лучший способ обучения :-) 18.12.2019df
есть заголовок столбцаrow
? Вы можете подумать, что это какой-то атрибут DataFrame, но совершенно ясно, что это имя столбца. Вам решать, как создавать и определять заголовки столбцов, поэтому, если вы используете другой, используйте его (например,df.my_column_name.split(...)
). 18.12.2019