使用正则表达式将DataFrame列拆分为列?

时间:2018-05-03 17:41:32

标签: python python-3.x python-2.7

我有一个包含两列的DataFrame,第二个具有以下格式:

1 {{continuity 1.0000e+00} {x-velocity 0.0000e+00} {y-velocity 4.4010e-02} {z-velocity 9.5681e-04} {energy 1.1549e-07} }
2 {{continuity 1.0000e+00} {x-velocity 7.8788e-04} {y-velocity 1.2617e+01} {z-velocity 9.0445e-04} {energy 4.5605e-06} }
3 {{continuity 2.3250e-01} {x-velocity 1.6896e-03} {y-velocity 1.2536e-02} {z-velocity 9.8980e-03} {energy 3.4032e-06} }
4 {{continuity 8.0243e-02} {x-velocity 2.2180e-03} {y-velocity 1.3189e-02} {z-velocity 1.0225e-02} {energy 4.6336e-07} }
5 {{continuity 7.0923e-02} {x-velocity 2.2674e-03} {y-velocity 1.2308e-02} 

我尝试使用正则表达式将其拆分为列,通过获取第一个数字,然后将所有数字放在括号之间" {}"并给他们以下名称:

names=['iter', 'x', 'x-vel', 'y-vel', 'z-vel', 'energy']

然而,我似乎并没有让正则表达式发挥作用,这是我在一个简单的例子中所做的:

输入

>>> a = "1 {{continuity 1.0000e+00} {x-velocity 0.0000e+00} {y-velocity 4.4010e-02} {z-velocity 9.5681e-04} {energy 1.1549e-07} }"
>>> re.findall("(\d*) {*\{\D*(.*?)\}", a)

结果

 >>> [('1', '1.0000e+00'), ('', '0.0000e+00'), ('', '4.4010e-02'), ('', '9.5681e-04'), ('', '1.1549e-07')]

正如你所看到的,我的正则表达式一直在寻找每个{}出现的数字,但我不希望这种情况发生,怎么做?

预期行为

 >>> [('1'), ('1.0000e+00'), ('0.0000e+00'), ('4.4010e-02'), ('9.5681e-04'), ('1.1549e-07')]

当我的正则表达式有效时,我试图为所有列分配一行看起来像这样的行:

df[names] = df.first.str.extract(r'(\d*) {*\{\D*(.*?)\}', expand=True)

我对数据帧非常陌生,这是解决此问题的正确方法吗?

非常感谢任何帮助,提前谢谢!

1 个答案:

答案 0 :(得分:2)

首先,让我们根据问题中的一些数据制作一系列文章。

import pandas as pd    

data = pd.Series('''\
1 {{continuity 1.0000e+00} {x-velocity 0.0000e+00} {y-velocity 4.4010e-02} {z-velocity 9.5681e-04} {energy 1.1549e-07} }
2 {{continuity 1.0000e+00} {x-velocity 7.8788e-04} {y-velocity 1.2617e+01} {z-velocity 9.0445e-04} {energy 4.5605e-06} }
3 {{continuity 2.3250e-01} {x-velocity 1.6896e-03} {y-velocity 1.2536e-02} {z-velocity 9.8980e-03} {energy 3.4032e-06} }
4 {{continuity 8.0243e-02} {x-velocity 2.2180e-03} {y-velocity 1.3189e-02} {z-velocity 1.0225e-02} {energy 4.6336e-07} }'''
          .split('\n'))
print(data)
0    1 {{continuity 1.0000e+00} {x-velocity 0.0000e...
1    2 {{continuity 1.0000e+00} {x-velocity 7.8788e...
2    3 {{continuity 2.3250e-01} {x-velocity 1.6896e...
3    4 {{continuity 8.0243e-02} {x-velocity 2.2180e...
dtype: object
       0     

第一个选项是一个简单的正则表达式,可以按顺序查找所有数字。使用extractall查找每个字符串中的每个匹配项。这可能足够好了。您仍然需要为列命名,这并不难。这将有一个MultiIndex(稍微高一点),因为每个匹配可能有多个组(但这个正则表达式只有一个组),因此需要.unstack()它。

print(data.str.extractall(r'(\d[\d.e+-]*)').unstack())
match  0           1           2           3           4           5
0      1  1.0000e+00  0.0000e+00  4.4010e-02  9.5681e-04  1.1549e-07
1      2  1.0000e+00  7.8788e-04  1.2617e+01  9.0445e-04  4.5605e-06
2      3  2.3250e-01  1.6896e-03  1.2536e-02  9.8980e-03  3.4032e-06
3      4  8.0243e-02  2.2180e-03  1.3189e-02  1.0225e-02  4.6336e-07     

或者,您可以使用命名组regex。这是一个相当简单的模板,可以从其中一个字符串构建。这会将正则表达式中的名称放入列中。但名称必须是有效的Python标识符。 (x_vel,而非x-vel)。但这可能是你想要的,因为它允许你作为attrs访问列(如df.x_vel而不是df['x-vel'])。这个(?P<foo>...)命名组语法全部在re模块文档中解释。

print(
    data.str.extract(r'(?P<iter>\d+) {{continuity (?P<x>[^}]+)} {x-velocity (?P<x_vel>[^}]+)} {y-velocity (?P<y_vel>[^}]+)} {z-velocity (?P<z_vel>[^}]+)} {energy (?P<energy>[^}]+)} }',
                     expand=False))
  iter           x       x_vel       y_vel       z_vel      energy
0    1  1.0000e+00  0.0000e+00  4.4010e-02  9.5681e-04  1.1549e-07
1    2  1.0000e+00  7.8788e-04  1.2617e+01  9.0445e-04  4.5605e-06
2    3  2.3250e-01  1.6896e-03  1.2536e-02  9.8980e-03  3.4032e-06
3    4  8.0243e-02  2.2180e-03  1.3189e-02  1.0225e-02  4.6336e-07

请注意,我们在此处使用extract而不是extractall,因为正则表达式本身有多个组。