我的测试数据框看起来像这样:
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
不同之处在于我的所有列子名都不同并且没有共性(而在其他帖子中,名称中的所有内容都有组或类)。是否有正则表达式字符串或其他方法,我可以使用它来进行堆叠?
答案 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)
这是另一种方式。它假设低/高组分别以Low
和High
结尾,因此我们可以使用.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