Как разбить колонну панды с условным - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть журнал df, в котором df у меня есть столбец Description.Похоже.

Description
Machine x : Turn off
Another action here
Another action here
Machine y : Turn off
Machine x : Turn on
Another action here

И мне нужно разделить только строки с ":"

Как:

Description               Machine           Action
Machine x : Turn off      Machine x         Turn off
Another action here
Another action here
Machine y : Turn off      Machine y         Turn off
Machine x : Turn on       Machine x         Turn on
Another action here

Я уже пробовал:

s = df["Description"].apply(lambda x:x.split(":"))
df["Action"] = s.apply(lambda x: x[1])
df["Machine"] = s.apply(lambda x: x[0])

И что-то с "начинается с".

Ответы [ 6 ]

0 голосов
/ 09 декабря 2018

StringMethods полезны и удобны, но обычно работают не очень хорошо.

Я бы рекомендовал использовать конструктор по умолчанию и обработку строк на чистом python

df[['Machine', 'Action']] = pd.DataFrame([x.split(':') for x in df.Description]).dropna()

Сроки лучше, чем .str опции доступа.

df = pd.concat([df]*1000)
%timeit pd.DataFrame([x.split(':') for x in df.Description]).dropna()
4.47 ms ± 252 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df.Description.str.split(':',expand=True).dropna()
14.9 ms ± 323 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df.Description.str.extract('(.*) : (.*)',expand=True)
16.6 ms ± 393 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit pd.concat([df, df.Description.str.extract('(?P<Machine>[^:]+)\s+:\s+(?P<Action>[^:]+)').fillna('')], axis=1)
22.5 ms ± 448 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
0 голосов
/ 09 декабря 2018

Мое предложение:

msk = df.Description.str.contains(':')
df[['Machine', 'Action']] = df.Description.str.split(':', 1, expand=True).where(msk, '')

Сначала создайте маску - для каких строк можно получить непустые значения.

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

0 голосов
/ 09 декабря 2018

Просто используя split с expand=True

df[['Machine', 'Action']] =df.Description.str.split(':',expand=True).dropna()
df
            Description     Machine     Action
0  Machine x : Turn off  Machine x    Turn off
1   Another action here         NaN        NaN
2   Another action here         NaN        NaN
3  Machine y : Turn off  Machine y    Turn off
4   Machine x : Turn on  Machine x     Turn on
5   Another action here         NaN        NaN
0 голосов
/ 09 декабря 2018

С функцией pd.Series.str.extract и специальным шаблоном регулярных выражений (охватывает потенциальные несколько пробелов вокруг : разделителя):

In [491]: df
Out[491]: 
            Description
0  Machine x : Turn off
1   Another action here
2   Another action here
3  Machine y : Turn off
4   Machine x : Turn on
5   Another action here

In [492]: pd.concat([df, df.Description.str.extract('(?P<Machine>[^:]+)\s+:\s+(?P<Action>[^:]+)').fillna('')], axis=1)
Out[492]: 
            Description    Machine    Action
0  Machine x : Turn off  Machine x  Turn off
1   Another action here                     
2   Another action here                     
3  Machine y : Turn off  Machine y  Turn off
4   Machine x : Turn on  Machine x   Turn on
5   Another action here                     
0 голосов
/ 09 декабря 2018

Вы можете использовать str.extract с подходящим regex.Это найдет все значения вокруг : (также удаляя пробелы вокруг двоеточия):

df[['Machine', 'Action']] = df.Description.str.extract('(.*) : (.*)',expand=True)

>>> df
            Description    Machine    Action
0  Machine x : Turn off  Machine x  Turn off
1   Another action here        NaN       NaN
2   Another action here        NaN       NaN
3  Machine y : Turn off  Machine y  Turn off
4   Machine x : Turn on  Machine x   Turn on
5   Another action here        NaN       NaN

# df[['Machine', 'Action']] = df.Description.str.extract('(.*) : (.*)',expand=True).fillna('')
0 голосов
/ 09 декабря 2018

При наличии фрейма данных

>>> df
            Description
0  Machine x : Turn off
1   Another action here
2   Another action here
3  Machine y : Turn off
4   Machine x : Turn on
5   Another action here

Я бы подошел к этому через Series.str.split(splitter, expand=True).

>>> has_colon = df['Description'].str.contains(':')
>>> df[['Machine', 'Action']] = df.loc[has_colon, 'Description'].str.split('\s*:\s*', expand=True)
>>> df
            Description    Machine    Action
0  Machine x : Turn off  Machine x  Turn off
1   Another action here        NaN       NaN
2   Another action here        NaN       NaN
3  Machine y : Turn off  Machine y  Turn off
4   Machine x : Turn on  Machine x   Turn on
5   Another action here        NaN       NaN

Если вы предпочитаете пустые строки, вы можете заменить ячейки NaN с помощью

>>> df.fillna('')
            Description    Machine    Action
0  Machine x : Turn off  Machine x  Turn off
1   Another action here                     
2   Another action here                     
3  Machine y : Turn off  Machine y  Turn off
4   Machine x : Turn on  Machine x   Turn on
5   Another action here 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...