Если строка не существует, проверьте и приписайте значение соответственно в Python - PullRequest
3 голосов
/ 16 октября 2019

У меня есть кадр данных, содержащий 3 столбца:

[in]:

import pandas as pd
import numpy as np
df = pd.DataFrame([['Circle', 'Circle', 'Polygon', 'Polygon',"Trapezoid"], 
                   [0, 1, 0, 1,1], [28152, 9168, 24741, 11402,5000]], 
                   ['nom_1', 'target', 'id']).T 

[out]:

       nom_1 target     id
0     Circle      0  28152
1     Circle      1   9168
2    Polygon      0  24741
3    Polygon      1  11402
4  Trapezoid      1   5000

Теоретически каждая геометрическая форма должна иметь значение 0 или 1 в целевом столбце. Идентификатор представляет счет. Мне нужно соотношение 1 / (1 + 0) для каждой геонетрической фигуры в столбце id.

Например, счетчик идентификаторов "Круга" для цели 1 равен 9168, а для 0 - 28152. Мне нужно вычисление: (9168) / (9168 + 28152). Я выполняю этот расчет с помощью этого фрагмента кода.

[in]:

ColumnTarget = df[["id","nom_1","target"]]
ColumnGrouped = ColumnTarget.groupby(["nom_1","target"]).count()["id"].reset_index()
ColumnCalculation = ColumnGrouped.groupby("nom_1").apply(lambda row: (row[row.target ==1]["id"].iloc[0]) / (row[row.target ==0]["id"].iloc[0] + row[row.target ==1]["id"].iloc[0]))

[out]:

IndexError: single positional indexer is out-of-bounds

Однако, когда геометрическая форма не имеет ни 1, ни 0 целевой строки, я получаю IndexError. В этом случае у «Трапеции» отсутствует целевая строка 0. Поэтому, если для геометрической формы присутствуют обе 0,1 цели, мне нравится расчет, который я изложил выше. Если 1 цель отсутствует, я хочу, чтобы результат был равен 0, а если 0 цель отсутствует, результат должен быть равен 1. Например, для «Трапеции» результат должен быть 1.

Вот что я пытался:

[in]:

ColumnTarget = df[["id","nom_1","target"]]
ColumnGrouped = ColumnTarget.groupby(["nom_1","target"]).count()["id"].reset_index()
ColumnCalculation = ColumnGrouped.groupby("nom_1").apply(lambda row: 0 if row[row.target ==1].all() is False else (1 if row[row.target ==0].all() is False else ((row[row.target ==1]["id"].iloc[0]) / (row[row.target ==0]["id"].iloc[0] + row[row.target ==1]["id"].iloc[0]))))

[out]:

IndexError: single positional indexer is out-of-bounds

output_df = pd.DataFrame({"nom_1":["Circle","Polygon","Trapezoid"],"result": [0.24565916398713827,0.3154691088177517,1]})

Ответы [ 2 ]

4 голосов
/ 16 октября 2019

Используйте transform и div

df['id'].div(df.groupby('nom_1').id.transform('sum'), axis=0)

       nom_1 target     id     ratio
0     Circle      0  28152  0.754341
1     Circle      1   9168  0.245659
2    Polygon      0  24741  0.684531
3    Polygon      1  11402  0.315469
4  Trapezoid      1   5000         1

Очевидно, что вы можете редактировать df, чтобы визуализировать только те строки с target == 1

df[df.target == 1]

       nom_1 target     id     ratio
1     Circle      1   9168  0.245659
3    Polygon      1  11402  0.315469
4  Trapezoid      1   5000         1
2 голосов
/ 16 октября 2019

Используйте index, чтобы выровнять расчет (я добавил фигуру без цели == 1). Это предполагает, что у вас нет ничего дублированного на ['nom_id', 'target']:

df = pd.DataFrame([['Circle', 'Circle', 'Polygon', 'Polygon',"Trapezoid", 'Octagon'], 
                   [0, 1, 0, 1, 1, 0], [28152, 9168, 24741, 11402,5000, 6000]], 
                   ['nom_1', 'target', 'id']).T 

df = df.set_index('nom_1')
u = df.loc[df.target.eq(1), 'id']
v = df.loc[df.target.eq(0), 'id']

                                    # - 0 When Target == 1 is missing
                                    # |
s = u.divide(u.add(v, fill_value=0)).fillna(0)
#nom_1
#Circle       0.245659
#Octagon      0.000000
#Polygon      0.315469
#Trapezoid    1.000000
#Name: id, dtype: float64
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...