Сложное разделение и группировка для отображения процентов (Pandas / Python)

#python #pandas #numpy

#python #pandas #numpy

Вопрос:

Дилемма:

У меня есть набор данных, df, где я хотел бы разделить и сгруппировать сложный формат в определенном столбце и отобразить проценты. Я разделяю значения в столбце Type, сосредоточив внимание на первых трех «словах» (например) Hello-HEL-HE — и значении, за которым следует буква T -12T

 There are    3  unique counts    of   Hello-HEL-HE-A6123-123A-12T
             2  unique counts    of   Hello-HEL-HE-A6123-123A-50T
             1  unique count(s)  of   Happy-HAP-HA-R650-570A-90T    
 

Данные:

 Type                                    Value

Hello-HEL-HE-A6123-123A-12T_TYPE-v.A    1,111,111
Hello-HEL-HE-A6123-123A-12T_TYPE-v.B    111,111
Hello-HEL-HE-A6123-123A-12T_TYPE-v.E    2,345,667
Hello-HEL-HE-A6123-123A-50T_TYPE-v.C    222,334
Hello-HEL-HE-A6123-123A-50T_TYPE-v.A    89
Happy-HAP-HA-R650-570A-90T_version-v.A  6
 

Желаемый результат:

 Type                                    Percent

Hello-HEL-HE-12T                        50%
Hello-HEL-HE-50T                        33%
Happy-HAP-HA-90T                      16.6%
 

Выполнение:

(предлагается разделить на ‘_’, а затем разделить на ‘-‘)

 df.str.split(pat="_")                                      #separating by hyphen

(df['Type'].value_counts(normalize=True) * 100).to_frame()  #groupby
 

Однако я не уверен, как разделить каждый тип на: Hello-HEL-HE, а также -12T

Любое предложение приветствуется

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

1. Как вы это определяете -12T и -90T какие части вас интересуют? Это потому , что за ними следуют две цифры 'T' , или потому , что они являются последним битом перед '_' ?

2. Из-за размещения — я вижу, что они находятся на «6-м» месте, разделенном дефисами

3. часть, которая находится на 5-м месте, будет '12T_TYPE'

4. df['Type'].value_counts(normalize=True) * 100).to_frame() не может быть правильным, отсутствует ( . Как насчет разделения _ , а затем разделения - , а затем объединения первых трех и последней строки вместе, чтобы создать новый индекс?

5. хорошо, спасибо @PaulBrennan, я попробую это

Ответ №1:

Давайте попробуем

 df=df.assign(Value=df['Value'].str.split(','),Type=df.Type.str.split('_').str[0])
df2=(df['Type'].value_counts(normalize=True)*100).to_frame('%')
df2.rename_axis(index='Type')
 



                                   %
Type                                  
Hello-HEL-HE-A6123-123A-12T  50.000000
Hello-HEL-HE-A6123-123A-50T  33.333333
Happy-HAP-HA-R650-570A-90T   16.666667
 

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

1. хорошее использование value_counts !

2. Хорошо, спасибо — просто интересно, зачем нам ссылаться на столбец значений, когда мы выполняем группировки по типу col?

3. Посмотрите мои правки, если это поможет. Это природа вычислений, которая действительно так работает.

4. Это работает для меня. Если у вас нет других столбцов. Это данные, которые я использовал, если это может помочь; df=pd.DataFrame({'Type':['Hello-HEL-HE-A6123-123A-12T_TYPE-v.A','Hello-HEL-HE-A6123-123A-12T_TYPE-v.B','Hello-HEL-HE-A6123-123A-12T_TYPE-v.E','Hello-HEL-HE-A6123-123A-50T_TYPE-v.C','Hello-HEL-HE-A6123-123A-50T_TYPE-v.A','Happy-HAP-HA-R650-570A-90T_version-v.A'],'Value':['1,111,111','111,111','2,345,667','222,334','89','6']})

5. Проблема только в том, что проблема во взрыве Value . Не могли бы вы попробовать df=df.assign(Type=df.Type.str.split('_').str[0]) df2=(df['Type'].value_counts(normalize=True)*100).to_frame('%') print(df2.rename_axis(index='Type'))

Ответ №2:

Вы могли бы сделать что-то вроде:

 df['Type'].str.split('_').str[0].value_counts(normalize=True)

Hello-HEL-HE-A6123-123A-12T    0.500000
Hello-HEL-HE-A6123-123A-50T    0.333333
Happy-HAP-HA-R650-570A-90T     0.166667
 

Если вам нужна эта конкретная форма, то:

 tmp = df['Type'].str.split('_').str[0].value_counts(normalize=True).reset_index(name='percentage').rename(columns={'index': 'Type'})

tmp['percentage'] = tmp['percentage'].apply(lambda x: '{:.2f}%'.format(100*x))

tmp

Type percentage
Hello-HEL-HE-A6123-123A-12T     50.00%
Hello-HEL-HE-A6123-123A-50T     33.33%
Happy-HAP-HA-R650-570A-90T     16.67%

 

Ответ №3:

Если вы хотите получить все поля перед подчеркиванием:

 key = df.Type.str.split(r'_', n=1, expand=True)[0]
key

# out:
0    Hello-HEL-HE-A6123-123A-12T
1    Hello-HEL-HE-A6123-123A-12T
2    Hello-HEL-HE-A6123-123A-12T
3    Hello-HEL-HE-A6123-123A-50T
4    Hello-HEL-HE-A6123-123A-50T
5     Happy-HAP-HA-R650-570A-90T
 

Если вместо этого вам нужны первые три слова и последнее перед подчеркиванием, то:

 a = df.Type.str.split(r'_', n=1, expand=True)[0].str.split(r'-', expand=True)
sel = list(a.columns)
sel = sel[1:3]   sel[-1:]
key = a[0].str.cat(a[sel], '-')
key

# out:
0    Hello-HEL-HE-12T
1    Hello-HEL-HE-12T
2    Hello-HEL-HE-12T
3    Hello-HEL-HE-50T
4    Hello-HEL-HE-50T
5    Happy-HAP-HA-90T
 

В любом случае вы можете затем сгруппировать этот ключ:

 cnt = df.groupby(key)['Value'].count()
100 * cnt / cnt.sum()

# out:
Happy-HAP-HA-90T    16.666667
Hello-HEL-HE-12T    50.000000
Hello-HEL-HE-50T    33.333333