如何使用标签上索引的特定列中的值拆分字符串?

问题描述

我有以下数据

Index   Data
0       100CO
1       50CO-50PET
2       98CV-2EL
3       50CV-50CO
.       .
.       .
.       .

我必须创建将数据格式拆分为不同的列,每个列都有各自的标题和值,结果应如下所示:

Index   Data          CO        PET      CV    EL
0       100CO         100       0        0     0
1       50CO-50PET    50        50       0     0
2       98CV-2EL      0         0        98    2
3       50CV-50CO     50        0        50    0
.       .
.       .
.       .

数据不限于CO / PET / CV / EL,将需要尽可能多的列,每个列均显示其对应的值。

.str.split('-',expand=True)函数只会分隔数据并将所有第一个值保留在同一列中,而不会重命名每一列。

有没有办法在python中实现呢?

解决方法

您可以这样做:

df.Data.str.split('-').explode().str.split(r'(?<=\d)(?=\D)',expand = True). \
   reset_index().pivot('index',1,0).fillna(0).reset_index()

1  Index   CO  CV EL PET
0      0  100   0  0   0
1      1   50   0  0  50
2      2    0  98  2   0
3      3   50  50  0   0
,

想法首先是将值除以-,然后将数字和没有数字的值提取到元组,追加到列表并转换为字典。它以列表解析的形式传递给DataFrame cosntructor,替换为misisng值并转换为数字:

import re

def f(x):
    L = []
    for val in x.split('-'):
        k,v = re.findall('(\d+)(\D+)',val)[0]
        L.append((v,k))
    return dict(L)

df = df.join(pd.DataFrame([f(x) for x in df['Data']],index=df.index).fillna(0).astype(int))
print (df)
         Data   CO  PET  CV  EL
0       100CO  100    0   0   0
1  50CO-50PET   50   50   0   0
2    98CV-2EL    0    0  98   2
3   50CV-50CO   50    0  50   0

如果数据中存在一些没有数字或数字的值,则应更改解决方案以更通用:

print (df)
         Data
0       100CO
1  50CO-50PET
2    98CV-2EL
3   50CV-50CO
4         AAA
5          20

def f(x):
    L = []
    for val in x.split('-'):
        extracted = re.findall('(\d+)(\D+)',val)
        if len(extracted) > 0:
            k,v = extracted[0]
            L.append((v,k))
        else:
            if val.isdigit():
                L.append(('No match digit',val)) 
            else:
                L.append((val,0))
    return dict(L)
    

df = df.join(pd.DataFrame([f(x) for x in df['Data']],index=df.index).fillna(0).astype(int))
print (df)
         Data   CO  PET  CV  EL  AAA  No match digit
0       100CO  100    0   0   0    0               0
1  50CO-50PET   50   50   0   0    0               0
2    98CV-2EL    0    0  98   2    0               0
3   50CV-50CO   50    0  50   0    0               0
4         AAA    0    0   0   0    0               0
5          20    0    0   0   0    0              20
,

尝试一下:

import pandas as pd
import re

df = pd.DataFrame({'Data':['100CO','50CO-50PET','98CV-2EL','50CV-50CO']})

split_df = pd.DataFrame(df.Data.apply(lambda x: {re.findall('[A-Z]+',el)[0] : re.findall('[0-9]+',el)[0] \
                                  for el in x.split('-')}).tolist())
split_df = split_df.fillna(0)

df = pd.concat([df,split_df],axis = 1)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...