2015-08-07 5 views
1

У меня есть тестовый dataframe, который выглядит примерно так:Панды разделить имя столбца

data = pd.DataFrame([[0,0,0,3,6,5,6,1],[1,1,1,3,4,5,2,0],[2,1,0,3,6,5,6,1],[3,0,0,2,9,4,2,1]], columns=["id", "sex", "split", "group0Low", "group0High", "group1Low", "group1High", "trim"]) 

grouped = data.groupby(['sex','split']).mean() 

stacked = grouped.stack().reset_index(level=2) 
stacked.columns = ['group_level', 'mean'] 

Далее, я хочу, чтобы отделить group_level и укладывают эти 2 новые факторы:

stacked['group'] = stacked.group_level.str[:6] 
stacked['level'] = stacked.group_level.str[6:] 

Это все работы хорошо. Мой вопрос таков:

Это работает, если имена моих столбцов («group0Low», «group0High», «group1Low», «group1High») имеют нечто общее между собой.

Что делать, если вместо этого имена столбцов больше напоминают «routeLow», «routeHigh», «landmarkLow», «landmarkHigh»? Как использовать str для разделения group_level в этом случае?

Этот вопрос похож на этот публикуемую здесь: Slice/split string Series at various positions

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

ответ

2

Вот еще один способ. Он предполагает, что нижняя/верхняя группа заканчивается словами Low и High соответственно, так что мы можем использовать .str.endswith(), чтобы определить, какие строки являются Low/High.

Вот выборочные данные

df = pd.DataFrame('group0Low group0High group1Low group1High routeLow routeHigh landmarkLow landmarkHigh'.split(), columns=['group_level']) 
df 

    group_level 
0  group0Low 
1 group0High 
2  group1Low 
3 group1High 
4  routeLow 
5  routeHigh 
6 landmarkLow 
7 landmarkHigh 

Использование np.where, мы можем сделать следующий

df['level'] = np.where(df['group_level'].str.endswith('Low'), 'Low', 'High') 
df['group'] = np.where(df['group_level'].str.endswith('Low'), df['group_level'].str[:-3], df['group_level'].str[:-4]) 

df 

    group_level level  group 
0  group0Low Low group0 
1 group0High High group0 
2  group1Low Low group1 
3 group1High High group1 
4  routeLow Low  route 
5  routeHigh High  route 
6 landmarkLow Low landmark 
7 landmarkHigh High landmark 
+0

спасибо за идею. Я адаптировал его, используя str.contains(), и теперь все работает очень хорошо! – Simon

2

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

In [30]:  
s = pd.Series(['routeHigh', 'routeLow', 'landmarkHigh', 
       'landmarkLow', 'routeMid', 'group0Level']) 
s.str.extract('([\d\w]*)([A-Z][\w\d]*)') 

Out[30]: 
    0  1 
0 route High 
1 route Low 
2 landmark High 
3 landmark Low 
4 route Mid 
5 group0 Level 

Вы можете даже назвать столбцы результата в одной и той же линии, делая

s.str.extract('(?P<group>[\d\w]*)(?P<Level>[A-Z][\w\d]*)') 

Так что в вашем случае использования вы можете do

group_level_df = stacked.group_level.extract('(?P<group>[\d\w]*)(?P<Level>[A-Z][\w\d]*)') 
stacked = pd.concat([stacked, group_level_df]) 

Вот еще один подход, который предполагает только знание названий уровней заранее. Предположим, у вас есть три уровня:

lower = stacked.group_level.str.lower() 
for level in ['low', 'mid', 'high']: 

    rows_in = lower.str.contains(level) 
    stacked.loc[rows_in, 'level'] = level.capitalize() 
    stacked.loc[rows_in, 'group'] = stacked.group_level[rows_in].str.replace(level, '') 

Который должен работать до тех пор, пока уровень не отображается в названии группы, а также, например, 'HighballHigh. В случаях, когда group_level не содержал ни одного из этих уровней, вы должны были бы получить нулевые значения в соответствующих строках.

+0

Я видел ваш скомпонованной ответ, который на самом деле работал отлично, но я вижу ограничения с использованием str.contains(). Меня интересует ваш подход str.extract, в котором вы одновременно называете столбцы. Однако, похоже, он работает только с серией, а не с файлами (ошибка: объект DataFrame не имеет атрибута «str»). Есть ли альтернатива? – Simon

+1

Нет, вам просто нужно сделать 'stacked.group_level.str.extract', то есть вызвать его в соответствующем столбце. Как вы говорите, это метод серии. Я использовал свою собственную серию, чтобы показать еще несколько примеров, поэтому я не добавил 'stacked.group_level'.Я удалил предварительный ответ, поскольку метод полосы не был хорош, но потом я подумал об использовании замены, которая находится во втором подходе выше. Если вы делаете это, не используйте полосу, используйте замену. – JoeCondron

+0

Если я делаю что-то вроде этого: stacked ['condition'] = stacked.condition.str.extract ('(? P [\ d \ w] *) (? P [AZ] [\ w \ d] *) '), он будет хранить только маршрут/ориентир в столбце, он игнорирует низкий/высокий коэффициент. Кажется, он пытается разделить 2 вещи в имени столбца и сохранить их в один столбец, называемый условием, когда мне действительно нужно создать 2 новых столбца, один для маршрута/ориентира и один для низкого/высокого – Simon

Смежные вопросы