Как разделить столбец фрейма данных Pandas на несколько столбцов на основе содержащегося в тексте значения - PullRequest
2 голосов
/ 17 октября 2019

Допустим, есть столбец, как показано ниже.

df = pd.DataFrame(['A-line B-station 9-min C-station 3-min',
                   'D-line E-station 8-min F-line G-station 5-min',
                   'G-line H-station 1-min I-station 6-min J-station 8-min'],
                    columns=['station'])

A, B, C - это просто произвольные символы, и есть целый ряд таких строк.

                                             station
0             A-line B-station 9-min C-station 3-min
1      D-line E-station 8-min F-line G-station 5-min
2  G-line H-station 1-min I-station 6-min J-stati...

Как можномы делаем столбцы, как показано ниже?

   Line1     Station1-1   Station1-2 Station1-3   Line2    Station2-1
0  A-line    B-station    C-station    null       null     null
1  D-line    E-station    null         null       F-line   G-station
2  G-line    H-station    I-station    J-station  null     null

stationX-X означает, что Station (номер строки) - (порядок станции)

Station1-1 означает первую станцию ​​для первой строки (line1)

Station1-2 означает вторую станцию ​​для первой линии (line1)

Station2-1 означает первую станцию ​​для второй линии (line2)

Я попытался разделить на разделитель;однако, это не работает, поскольку в каждой строке разное количество линий и станций.

Что мне может понадобиться, это разделить столбцы на основе содержащихся в них символов. Например, я мог бы сохранить первую '-line' для Line1 и сохранить первую '-station' для station1-1.

У кого-нибудь есть идеи, как это сделать?

Есть небольшие мыслиПомоги мне!

Спасибо!

1 Ответ

4 голосов
/ 17 октября 2019

Сначала создайте Series с Series.str.split и DataFrame.stack:

s = df['station'].str.split(expand=True).stack()

Затем удалите значения, заканчивающиеся min на boolean indexing с Series.str.endswith:

df1 = s[~s.str.endswith('min')].to_frame('data').rename_axis(('a','b'))

Затем создайте счетчики для line с и station строк с фильтрацией и GroupBy.cumcount:

df1['Line'] = (df1[df1['data'].str.endswith('line')]
                         .groupby(level=0)
                         .cumcount()
                         .add(1)
                         .astype(str))
df1['Line'] = df1['Line'].ffill()

df1['station'] = (df1[df1['data'].str.endswith('station')]
                         .groupby(['a','Line'])
                         .cumcount()
                         .add(1)
                         .astype(str))

Создать серию с объединением, заменить отсутствующие значения на df1['Line'] на Series.fillna:

df1['station'] = (df1['Line'] + '-' + df1['station']).fillna(df1['Line'])

Изменить на DataFrame.set_index с DataFrame.unstack:

df1 = df1.set_index('station', append=True)['data'].reset_index(level=1, drop=True).unstack()

Rename имена столбцов - не раньше, чтобы избежать неправильной сортировки:

df1 = df1.rename(columns = lambda x: 'Station' + x if '-' in x else 'Line' + x)

Удалить имя столбца:

df1.columns.name = None
df1.index.name = None
print (df1)
    Line1 Station1-1 Station1-2 Station1-3   Line2 Station2-1
0  A-line  B-station  C-station        NaN     NaN        NaN
1  D-line  E-station        NaN        NaN  F-line  G-station
2  G-line  H-station  I-station  J-station     NaN        NaN
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...