Pandas拆分列名

时间:2015-08-07 21:30:50

标签: python regex pandas

我的测试数据框看起来像这样:

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并堆叠这两个新因素:

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

一切正常。我的问题是:

如果我的专栏名称(" group0Low"," group0High"," group1Low"," group1High")有共同点彼此。

如果我的列名更像是" routeLow"," routeHigh"," landmarkLow"," landmarkHigh&#34 ;?在这种情况下,我如何使用str来拆分group_level?

此问题类似于此处发布的问题:Slice/split string Series at various positions

不同之处在于我的所有列子名都不同并且没有共性(而在其他帖子中,名称中的所有内容都有组或类)。是否有正则表达式字符串或其他方法,我可以使用它来进行堆叠?

2 个答案:

答案 0 :(得分: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]*)')

所以在你的用例中你可以做到

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, '')

只要级别也不会出现在组名中,哪个应该有效,例如&#39; highballHigh&#39 ;.如果group_level没有包含任何这些级别,您最终会在相应的行中显示空值

答案 1 :(得分:2)

这是另一种方式。它假设低/高组分别以LowHigh结尾,因此我们可以使用.str.endswith()来识别哪些行为低/高。

以下是示例数据

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