Как разделить строку со значениями в их конкретных столбцах, индексированных на их метке?

#python-3.x #pandas #dataframe #split

#python-3.x #pandas #dataframe #разделить

Вопрос:

У меня есть следующие данные

 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?

Ответ №1:

Вы могли бы сделать:

 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
  

Комментарии:

1. Привет, спасибо за ответ. К сожалению, при объединении с исходной базой данных индекс не совпадает.

2. вы просто удаляете index имя

Ответ №2:

Идея заключается в том, чтобы сначала разделить значения на - , затем извлечь значения numbers и no numbers в кортежи, добавить в список и преобразовать в словари. Он передается в понимании списка в DataFrame cosntructor, заменяется ошибочными значениями и преобразуется в числовой:

 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
  

Ответ №3:

Попробуйте это:

 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)
  

Комментарии:

1. Привет, спасибо за ответ. К сожалению, при объединении с исходной базой данных индекс не совпадает.