Разбиение строки в DataFrame несколько раз - PullRequest
3 голосов
/ 03 июня 2019

У меня есть столбец в DataFrame, который содержит строку, из которой я должен извлечь два фрагмента информации различными разделителями:

ID  STR
280 11040402-38.58551%;11050101-9.29086%;11070101-52.12363%
351 11130203-35%;11130230-65%
510 11070103-69%
655 11090103-41.63463%;11160102-58.36537%
666 11130205-50.00%;11130207-50%

Я пытался использовать метод .apply в этой серии вместе с лямбда-функцией, чтобы выполнить расщепление за один раз, но безрезультатно:

df['STR'].apply(lambda x: y.split('-') for y in x.split(';'))

В идеале не только я мог бы разбить строку за один раз, но также отделить левую сторону - от правой стороны:

ID  STR.LEFT                       STR.RIGHT
280 [11040402, 11050101, 11070101] [38.58551%, 9.29086%, 52.12363%]
351 [11130203, 11130230]           [35%, 65%]
510 [11070103]                     [69%]
655 [11090103, 11160102]           [41.63463%, 58.36537%]
666 [11130205, 11130207]           [50.00%, 50%]

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

Ответы [ 3 ]

5 голосов
/ 03 июня 2019

Вы можете попробовать разделить несколько раз:

# set ID as index
df.set_index('ID', inplace=True)


new_series = df.STR.str.split(';', expand=True).stack().reset_index(level=-1,drop=True)

new_df = new_series.str.split('-', expand=True)

new_df.groupby('ID').agg(list).reset_index()

Выход:

      ID  0                                     1
--  ----  ------------------------------------  --------------------------------------
 0   280  ['11040402', '11050101', '11070101']  ['38.58551%', '9.29086%', '52.12363%']
 1   351  ['11130203', '11130230']              ['35%', '65%']
 2   510  ['11070103']                          ['69%']
 3   655  ['11090103', '11160102']              ['41.63463%', '58.36537%']
 4   666  ['11130205', '11130207']              ['50.00%', '50%']
4 голосов
/ 03 июня 2019

str.split

При условии, что шаблон всегда оставляет 'l-r;l-r;l-r...'

s = df.STR.str.split('-|;')
df[['ID']].join(pd.concat({'STR.LEFT': s.str[::2], 'STR.RIGTH': s.str[1::2]}, axis=1))

    ID                        STR.LEFT                         STR.RIGTH
0  280  [11040402, 11050101, 11070101]  [38.58551%, 9.29086%, 52.12363%]
1  351            [11130203, 11130230]                        [35%, 65%]
2  510                      [11070103]                             [69%]
3  655            [11090103, 11160102]            [41.63463%, 58.36537%]
4  666            [11130205, 11130207]                     [50.00%, 50%]

Если вы хотите разбить эти списки на отдельные строки

s = df.STR.str.split('-|;')
i = np.arange(len(df)).repeat(s.str.len() // 2)
d = {'STR.LEFT': np.concatenate(s.str[::2]),
     'STR.RIGHT': np.concatenate(s.str[1::2])}
df[['ID']].iloc[i].assign(**d).reset_index(drop=True)

    ID  STR.LEFT  STR.RIGHT
0  280  11040402  38.58551%
1  280  11050101   9.29086%
2  280  11070101  52.12363%
3  351  11130203        35%
4  351  11130230        65%
5  510  11070103        69%
6  655  11090103  41.63463%
7  655  11160102  58.36537%
8  666  11130205     50.00%
9  666  11130207        50%
3 голосов
/ 03 июня 2019

Достаточно одного вызова str.extractall, чтобы извлечь пары в отдельные столбцы. Затем вы можете объединить их в списки, используя groupby.

(df['STR'].str.extractall(r'(.*?)-(.*?)(?=;|$)')
          .groupby(level=0)
          .agg(list)
          .set_axis(['STR.LEFT', 'STR.RIGHT'], axis=1, inplace=False))

                           STR.LEFT                         STR.RIGHT
0  [11040402, ;11050101, ;11070101]  [38.58551%, 9.29086%, 52.12363%]
1  [11130203, ;11130230]             [35%, 65%]                      
2  [11070103]                        [69%]                           
3  [11090103, ;11160102]             [41.63463%, 58.36537%]          
4  [11130205, ;11130207]             [50.00%, 50%]  

Чтобы присоединиться с ID, вы просто используете: join.

(df['STR'].str.extractall(r'(.*?)-(.*?)(?=;|$)')
          .groupby(level=0)
          .agg(list)
          .set_axis(['STR.LEFT', 'STR.RIGHT'], axis=1, inplace=False)
          .join(df['ID'])

                           STR.LEFT                         STR.RIGHT   ID
0  [11040402, ;11050101, ;11070101]  [38.58551%, 9.29086%, 52.12363%]  280
1  [11130203, ;11130230]             [35%, 65%]                        351
2  [11070103]                        [69%]                             510
3  [11090103, ;11160102]             [41.63463%, 58.36537%]            655
4  [11130205, ;11130207]             [50.00%, 50%]                     666
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...