Разделение значений в столбце и создание новых столбцов небольшая проблема

#python #pandas

#python #pandas

Вопрос:

У меня есть данные опроса, в которых один столбец выглядит следующим образом:

 Evaluations_Col

E: 3, D: 3, C: 3, S: 3, E: 3, X, K: 3   
E: 1, D: 1, C: 1, S: 1, E: 1, X, K: 1
E: 2, D: 2, C: 2, S: 2, E: 2, X, K: 2 
E: 5, D: 5, C: 5, S: 5, E: 5, X, K: 5
E: 3, D: 1, C: 1, S: 1, E: 1, X, K: 1
  

ПРИМЕЧАНИЕ: мне нужно игнорировать значения X в столбцах.

Я хочу извлечь каждую оценку и разделить их как столбцы отдельно для каждого типа оценки. и в конце ожидаемые столбцы будут похожи:

 E_col    D_col     C_Col   ...

3          3         3
1          1         1
2          2         2
5          5         5
3          1         1
  

Возможно, я могу разделить их на запятую и получить список, подобный этому, [E: 3, D: 3, C: 3, S: 3, E: 3, K: 3] Что, как создать отдельный столбец для каждого и правильно распределить соответствующие значения?

Я могу нормально достичь этого, но значения X вызывают проблему со словарем bc… Как я могу это исключить?

 df1 = pd.DataFrame([dict([y.split(':') for y in x.split(',')]) for x in test_col])
df1.head()
  

ошибка

 ValueError: dictionary update sequence element #9 has length 1; 2 is required
  

Ответ №1:

Использование понимания списка и фильтрации строк, содержащих только разделитель ‘:’:

Давайте разберем понимание списка на части:

  1. Цикл по строкам : for x in test_col
  2. Разделение только строк (обозначаемых x ) на столбцы путем разделения на ‘,’ : for y in x.split(',')
  3. Разделение столбца на пару ключ-значение только в том случае, если существует разделитель ‘:’ : y.split(':') for y in x.split(',') ***only*** if ':' in y (это решает описанную проблему)

Код:

 import pandas as pd
import numpy as np

test_col = []
with open('data.csv', 'r') as f:
    test_col = [l.strip() for l in f.readlines()]

df = pd.DataFrame([dict([y.split(':') for y in x.split(',') if ':' in y]) for x in test_col])
print(df.head())
  

Вывод:

     E   D   C   S   E   K
0   3   3   3   3   3   3
1   1   1   1   1   1   1
2   2   2   2   2   2   2
3   5   5   5   5   5   5
4   3   1   1   1   1   1
  

Ответ №2:

Один из способов — использовать str.extractall :

 s = df["Value"].str.extractall(r"([A-Z]):s(d)").reset_index().groupby("level_0")

print (pd.DataFrame(s[1].agg(list).tolist(), columns=s[0].get_group(0).tolist()))

   E  D  C  S  E  K
0  3  3  3  3  3  3
1  1  1  1  1  1  1
2  2  2  2  2  2  2
3  5  5  5  5  5  5
4  3  1  1  1  1  1
  

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

1. Я получаю эту ошибку -> Length of passed values is 0, index implies 2.

Ответ №3:

используя str.split и stack

 df1 = (
    df["Evaluations_Col"]
    .str.split(",", expand=True)
    .stack()
    .str.split(":", expand=True)
    .set_index(0, append=True)
    .dropna()
    .unstack([1, 2])
    .droplevel(1,1)
)


    1                    
0   E   D   C   S   E   K
0   3   3   3   3   3   3
1   1   1   1   1   1   1
2   2   2   2   2   2   2
3   5   5   5   5   5   5
4   3   1   1   1   1   1