Как разделить столбец на два столбца?



у меня есть фрейм данных с одним столбцом, и я хотел бы разделить его на два столбца, с одним заголовком столбца как'fips' и другие 'row'



мой фрейм данных df выглядит так:



          row
0 00000 UNITED STATES
1 01000 ALABAMA
2 01001 Autauga County, AL
3 01003 Baldwin County, AL
4 01005 Barbour County, AL


Я не знаю, как использовать df.row.str[:] для достижения моей цели разделения ячейки строки. Я могу использовать df['fips'] = hello, чтобы добавить новый столбец и заполнить его с hello. Есть идеи?



         fips       row
0 00000 UNITED STATES
1 01000 ALABAMA
2 01001 Autauga County, AL
3 01003 Baldwin County, AL
4 01005 Barbour County, AL
954   8  

8 ответов:

там может быть лучший способ, но это один из подходов:

In [34]: import pandas as pd

In [35]: df
Out[35]: 
                        row
0       00000 UNITED STATES
1             01000 ALABAMA
2  01001 Autauga County, AL
3  01003 Baldwin County, AL
4  01005 Barbour County, AL

In [36]: df = pd.DataFrame(df.row.str.split(' ',1).tolist(),
                                   columns = ['flips','row'])

In [37]: df
Out[37]: 
   flips                 row
0  00000       UNITED STATES
1  01000             ALABAMA
2  01001  Autauga County, AL
3  01003  Baldwin County, AL
4  01005  Barbour County, AL

TL; DR версия:

для простого случая:

  • у меня есть текстовый столбец с разделителем и я хочу две колонки

самое простое решение-это:

df['A'], df['B'] = df['AB'].str.split(' ', 1).str

или вы можете создать создать фрейм данных с одним столбцом для каждой записи разделения автоматически с:

df['AB'].str.split(' ', 1, expand=True)

обратите внимание, как, в любом случае .tolist() метод не нужен. Так же как и zip().

In деталь:

решение Энди Хейдена является самым превосходным в демонстрации силы 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() do, Я рекомендую документы для простая версия Python метода.

но как вы идете из:

  • столбец, содержащий двухэлементные списки

to:

  • два столбца, каждый из которых содержит соответствующий элемент списков?

Ну, нам нужно поближе взглянуть на .str атрибут столбца.

это a магический объект, который используется для сбора методов, которые обрабатывают каждый элемент в столбце как строку, а затем применяют соответствующий метод в каждом элементе как можно эффективнее:

>>> 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

конечно, получение фрейма данных из разбиения столбца строк настолько полезно, что .str.split() метод может сделать это за вас с :

>>> 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

вы можете экстракт различные части довольно аккуратно, используя шаблон регулярного выражения:

In [11]: df.row.str.extract('(?P<fips>\d{5})((?P<state>[A-Z ]*$)|(?P<county>.*?), (?P<state_code>[A-Z]{2}$))')
Out[11]: 
    fips                    1           state           county state_code
0  00000        UNITED STATES   UNITED STATES              NaN        NaN
1  01000              ALABAMA         ALABAMA              NaN        NaN
2  01001   Autauga County, AL             NaN   Autauga County         AL
3  01003   Baldwin County, AL             NaN   Baldwin County         AL
4  01005   Barbour County, AL             NaN   Barbour County         AL

[5 rows x 5 columns]

чтобы объяснить несколько длинное регулярное выражение:

(?P<fips>\d{5})
  • соответствует пяти цифр (\d) и называет их "fips".

следующая часть:

((?P<state>[A-Z ]*$)|(?P<county>.*?), (?P<state_code>[A-Z]{2}$))

у (|) одна из двух вещей:

(?P<state>[A-Z ]*$)
  • соответствует любому числу (*) из заглавных букв или пробелов ([A-Z ]) и называет это "state" до конца строки ($),

или

(?P<county>.*?), (?P<state_code>[A-Z]{2}$))
  • соответствует все остальное (.*) то
  • запятая и Пробел тогда
  • соответствует двум цифрам state_code до конца строки ($).

пример:
обратите внимание, что первые две строки попали в "состояние" (оставив NaN в графстве и state_code столбцы), в то время как последние три попали в графство, state_code (оставив NaN в столбце state).

Если вы не хотите создавать новый фрейм данных, или если ваш фрейм данных имеет больше столбцов, чем только те, которые вы хотите разделить, вы можете:

df["flips"], df["row_name"] = zip(*df["row"].str.split().tolist())
del df["row"]  
df[['fips', 'row']] = df['row'].str.split(' ', n=1, expand=True)

можно использовать str.split по пробелам (разделитель по умолчанию) и параметру expand=True на DataFrame с присвоением новых столбцов:

df = pd.DataFrame({'row': ['00000 UNITED STATES', '01000 ALABAMA', 
                           '01001 Autauga County, AL', '01003 Baldwin County, AL', 
                           '01005 Barbour County, AL']})
print (df)
                        row
0       00000 UNITED STATES
1             01000 ALABAMA
2  01001 Autauga County, AL
3  01003 Baldwin County, AL
4  01005 Barbour County, AL



df[['a','b']] = df['row'].str.split(n=1, expand=True)
print (df)
                        row      a                   b
0       00000 UNITED STATES  00000       UNITED STATES
1             01000 ALABAMA  01000             ALABAMA
2  01001 Autauga County, AL  01001  Autauga County, AL
3  01003 Baldwin County, AL  01003  Baldwin County, AL
4  01005 Barbour County, AL  01005  Barbour County, AL

модификация при необходимости удалить исходный столбец с DataFrame.pop

df[['a','b']] = df.pop('row').str.split(n=1, expand=True)
print (df)
       a                   b
0  00000       UNITED STATES
1  01000             ALABAMA
2  01001  Autauga County, AL
3  01003  Baldwin County, AL
4  01005  Barbour County, AL

что же так:

df[['a','b']] = df['row'].str.split(n=1, expand=True)
df = df.drop('row', axis=1)
print (df)

       a                   b
0  00000       UNITED STATES
1  01000             ALABAMA
2  01001  Autauga County, AL
3  01003  Baldwin County, AL
4  01005  Barbour County, AL

если получаю ошибку:

#remove n=1 for split by all whitespaces
df[['a','b']] = df['row'].str.split(expand=True)

ValueError: столбцы должны быть той же длины, что и key

вы можете проверить и его вернуться 4 колонки DataFrame, а не только 2:

print (df['row'].str.split(expand=True))
       0        1        2     3
0  00000   UNITED   STATES  None
1  01000  ALABAMA     None  None
2  01001  Autauga  County,    AL
3  01003  Baldwin  County,    AL
4  01005  Barbour  County,    AL

тогда решение добавить новый DataFrame by join:

df = pd.DataFrame({'row': ['00000 UNITED STATES', '01000 ALABAMA', 
                           '01001 Autauga County, AL', '01003 Baldwin County, AL', 
                           '01005 Barbour County, AL'],
                    'a':range(5)})
print (df)
   a                       row
0  0       00000 UNITED STATES
1  1             01000 ALABAMA
2  2  01001 Autauga County, AL
3  3  01003 Baldwin County, AL
4  4  01005 Barbour County, AL

df = df.join(df['row'].str.split(expand=True))
print (df)

   a                       row      0        1        2     3
0  0       00000 UNITED STATES  00000   UNITED   STATES  None
1  1             01000 ALABAMA  01000  ALABAMA     None  None
2  2  01001 Autauga County, AL  01001  Autauga  County,    AL
3  3  01003 Baldwin County, AL  01003  Baldwin  County,    AL
4  4  01005 Barbour County, AL  01005  Barbour  County,    AL

С удалить исходный столбец (если есть и другая столбцы):

df = df.join(df.pop('row').str.split(expand=True))
print (df)
   a      0        1        2     3
0  0  00000   UNITED   STATES  None
1  1  01000  ALABAMA     None  None
2  2  01001  Autauga  County,    AL
3  3  01003  Baldwin  County,    AL
4  4  01005  Barbour  County,    AL   

Если вы хотите разделить строку на более чем два столбца на основе разделителя, вы можете опустить параметр "maximum splits".
Вы можете использовать:

df['column_name'].str.split('/', expand=True)

это автоматически создаст столько столбцов, сколько максимальное количество полей, включенных в любую из ваших начальных строк.

Я предпочитаю экспортировать соответствующие серии панд (т. е. столбцы, которые мне нужны), используя применить функция для разделения содержимого столбца на несколько серий, а затем вступить созданные столбцы в существующий фрейм данных. Конечно, исходный столбец должен быть удален.

например

 col1 = df["<col_name>"].apply(<function>)
 col2 = ...
 df = df.join(col1.to_frame(name="<name1>"))
 df = df.join(col2.toframe(name="<name2>"))
 df = df.drop(["<col_name>"], axis=1)

чтобы разделить два слова строки функция должна быть что-то вроде этого:

lambda x: x.split(" ")[0] # for the first element
lambda x: x.split(" ")[-1] # for the last element

Comments

    Ничего не найдено.