Question: I have the following dataframe:

```
>>> df = pd.DataFrame(['0123_GRP_LE_BNS', 'ABC_GRP_BNS', 'DEF_GRP', '456A_GRP_SSA'], columns=['P'])
>>> df
                 P
0  0123_GRP_LE_BNS
1      ABC_GRP_BNS
2          DEF_GRP
3     456A_GRP_SSA

```

and want to remove characters appear after GRP if they are not '\_LE', or remove characters after GRP\_LE.

The desired output is:

```
0     0123_GRP_LE
1         ABC_GRP
2         DEF_GRP
3        456A_GRP

```

I used the following pattern matching. the ouput was not expected:

```
>>> df['P'].replace({r'(.*_GRP)[^_LE].*':r'\1', r'(.*GRP_LE)_.*':r'\1'}, regex=True)
0     0123_GRP_LE
1     ABC_GRP_BNS
2         DEF_GRP
3    456A_GRP_SSA
Name: P, dtype: object

```

Why the negation in r'(.\*\_GRP)[^\_LE].\*' does not work?

Answer: 
You can use:

```
out = (df
 .set_axis(df.columns.str.split('.', expand=True), axis=1)
 .stack()
 .droplevel(1)
 )

```

Output:

```
      a     b
0  a111  b111
0  c222  d222
0  e333  f333

```

Or, if you have a single row:

```
(df.set_axis(df.columns.str.split('.', expand=True), axis=1)
   .stack()
   .reset_index(drop=True)
 )

```

Output:

```
      a     b
0  a111  b111
1  c222  d222
2  e333  f333

```
One option is with [pivot\_longer](https://pyjanitor-devs.github.io/pyjanitor/api/functions/#janitor.functions.pivot.pivot_longer) from [pyjanitor](https://pyjanitor-devs.github.io/pyjanitor/):

```py
# pip install pyjanitor
import pandas as pd
import janitor

df.pivot_longer(names_to = '.value', names_pattern = '(.).*')

      a     b
0  a111  b111
1  c222  d222
2  e333  f333

```

The `.value` is a placeholder, which determines what sub parts of the column labels remain as header. The regex group in `names_pattern` decides which parts are extracted.