Как разбить столбец на основе строки (если она существует) на отдельный столбец

1

У меня есть dataframe следующим образом:

df = pd.DataFrame({
'Event':['2018 Green Meeting','2018 Yellow Meeting','2018 Red Meeting',
'2017 Green Meeting','2017 Yellow Meeting','2017 Red Meeting',
'2016 Green Meeting','2016 Yellow Meeting','2016 Red Meeting',
'Blue Meeting','Purple Meeting','Green Meeting'],
'Count':[1,2,3,4,5,6,7,8,9,10,11,12]
})

Я хочу разбить столбец событий на два столбца "Год" и "Событие_Name", чтобы получить следующий результат:

df2 = pd.DataFrame({
'Year':['2018','2018','2018',
'2017','2017','2017',
'2016','2016','2016',
'Blue Meeting','Purple Meeting','Green Meeting'],
'Event_Name':['Green Meeting','Yellow Meeting','Red Meeting',
'Green Meeting','Yellow Meeting','Red Meeting',
'Green Meeting','Yellow Meeting','Red Meeting',
'Blue Meeting','Purple Meeting','Green Meeting'],
'Count':[1,2,3,4,5,6,7,8,9,10,11,12]
})

Когда я пытаюсь использовать regex для этого. Кажется, он не работает. Я получаю два столбца "Год" и "Событие_Name". Но год пуст.

Это то, что я использую:

df[['Year','Event_Name']] = df['Event'].str.split(r'\d{4}',expand=True)

Как я могу заставить это работать правильно?

  • 0
    Когда вы разбиваете шаблон, этот шаблон удаляется из результата. Например, 'one and two and three'.split('and') возвращает ['one ',' two ',' three'] ; 'и' удаляется из результата.
Теги:
pandas

4 ответа

7

Использование str.extract с fillna

df['Year']=df.Event.str.extract('(\d+)').fillna(df.Event)

то мы replace

df['even_name']=df.Event.str.replace('\d+', '')
  • 0
    Привет Вэнь. Мне нужно создать две колонки (1) Year (2) Event_Name. В итоге получается только один столбец Year. Более того, для последних трех строк, где нет года, он помещает Event_Name в столбец Year.
  • 0
    df['even_name']=df.Event.str.replace('\d+', '') @AlhpaDelta также обновляется в моем ответе.
Показать ещё 1 комментарий
4

pandas.Series.str.findall

s = df.Event.str.findall('(\d+|\D+)')

pd.DataFrame(dict(
    Count=df.Count,
    Event_Name=s.str[-1],
    Year=s.str[0]
))

    Count       Event_Name            Year
0       1    Green Meeting            2018
1       2   Yellow Meeting            2018
2       3      Red Meeting            2018
3       4    Green Meeting            2017
4       5   Yellow Meeting            2017
5       6      Red Meeting            2017
6       7    Green Meeting            2016
7       8   Yellow Meeting            2016
8       9      Red Meeting            2016
9      10     Blue Meeting    Blue Meeting
10     11   Purple Meeting  Purple Meeting
11     12    Green Meeting   Green Meeting

Non-регулярное выражение

def f(x):
  a, b = x.split(None, 1)
  if a.isdecimal():
    return a, b
  else:
    return (x,)

s = df.Event.apply(f)

pd.DataFrame(dict(
    Count=df.Count,
    Event_Name=s.str[-1],
    Year=s.str[0]
))

    Count       Event_Name            Year
0       1    Green Meeting            2018
1       2   Yellow Meeting            2018
2       3      Red Meeting            2018
3       4    Green Meeting            2017
4       5   Yellow Meeting            2017
5       6      Red Meeting            2017
6       7    Green Meeting            2016
7       8   Yellow Meeting            2016
8       9      Red Meeting            2016
9      10     Blue Meeting    Blue Meeting
10     11   Purple Meeting  Purple Meeting
11     12    Green Meeting   Green Meeting
  • 0
    Спасибо! Я использовал вариант этого, и он работал полностью. s = df ['EventName']. str.findall ('(\ d {4})') df ['YearFromName'] = s.str [0] t = df ['EventName']. str.findall (' (\ D +) ') df [' EventFromName '] = t.str [0] df.to_csv (os.path.join (staging_area_folder,' df_w_year_3.csv '), index = False)
  • 0
    Спасибо, есть ли преимущество использования не-регулярных выражений по сравнению с регулярными выражениями?
Показать ещё 2 комментария
3

Использовать extractall:

df[['Year','Event']] = df.Event.str.extractall('(\d{4})? ?(.+$)').reset_index('match', drop=True)

Выход:

             Event  Count  Year
0    Green Meeting      1  2018
1   Yellow Meeting      2  2018
2      Red Meeting      3  2018
3    Green Meeting      4  2017
4   Yellow Meeting      5  2017
5      Red Meeting      6  2017
6    Green Meeting      7  2016
7   Yellow Meeting      8  2016
8      Red Meeting      9  2016
9     Blue Meeting     10   NaN
10  Purple Meeting     11   NaN
11   Green Meeting     12   NaN
  • 0
    Спасибо, это лучше, но есть ли способ сделать так, чтобы в последних трех строках столбец Year был пуст или содержал nan?
  • 0
    @AlhpaDelta Конечно, избавься от этой второй строки. Нравится.
Показать ещё 3 комментария
0

Это должно сделать работу

def get_year(x):
    try:
        return int(x.split()[0])
    except:
        return None

def get_event_name(x):
    try:
        year = int(x.split()[0])
        return ' '.join(x.split()[1: ])
    except:
        return x

df['Year'] = df['Event'].apply(lambda x: get_year(x))
df['Event_Name'] = df['Event'].apply(lambda x: get_event_name(x))
df = df.drop(['Event', ], axis=1)
  • 0
    Это не работает. Это дает ценностные ошибки
  • 0
    потому что у «Синей встречи» нет года в приведенном примере, я предположил, что это ошибка
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню