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

Если адрес 1 и адрес 2 присутствуют: оценка 10

Если есть другие детали адреса: оценка 5 для каждого.

Проблема в том, что результат оценки неверен. Это 15 для обоих клиентов, но первый должен быть 25, второй должен быть 15.

Вот фиктивный кадр данных:

import numpy as np
import pandas as pd

df = pd.DataFrame({'address1':['foo','bar'],'address2':['foo','bar'],'city':['foo',np.nan],'country':['hello','bar'],'county':['foo','bar'],'should_be':['25','20']})

df


  address1 address2 city country county should_be
0      foo      foo  foo   hello    foo        25
1      bar      bar  NaN     bar    bar        20



Затем я применяю функцию, которая подсчитывает, какая информация об адресе есть / отсутствует, и добавляет оценку в дополнительный столбец:


def f(row):

    score = 0

    # if we have address1 and address2
    if (row['address1'] ==True) & (row['address2']==True) ==2:
        score += 10
    # if we have city data 
    if row['city']:
        score += 5
    # if we have country data
    if row['country']:
        score += 5
    # if we have county data                                                                                                                      
    if row['county']:
        score += 5

    return score

    score = 0

df['actual'] = df.apply(f, axis=1)

df

  address1 address2 city country county should_be  actual
0      foo      foo  foo   hello    foo        25      15
1      bar      bar  NaN     bar    bar        20      15

Прежде всего, то, как я это делаю, довольно грязно. Есть ли более эффективный способ оценки / проверки данных?

Во-вторых, как вы можете видеть, оба клиента получили 15 баллов, при этом первый должен иметь 25 баллов из-за наличия всех деталей адреса, а второй - 20.

Я ожидал, что счет будет сброшен до нуля после раздела ниже. Это также не суммирует оценки правильно. Куда я иду не так?

return score

score = 0

Если кто-нибудь может определить, где я иду не так, я был бы признателен. Кроме того, если у вас есть какие-либо советы, чтобы очистить или сделать этот код более читабельным, я весь слух. Спасибо.

2
SCool 1 Июл 2019 в 14:05

3 ответа

Лучший ответ

Я не уверен в более эффективном способе, но просто изменение вашей функции работает нормально:

def f(row):
    score = 0
    # if we have address1 and address2
    if not pd.isnull(row['address1']) and not pd.isnull(row['address2']):
        score += 10
    # if we have city data 
    if not pd.isnull(row['city']):
        score += 5
    # if we have country data
    if not pd.isnull(row['country']):
        score += 5
    # if we have county data                                                                                                                      
    if not pd.isnull(row['county']):
        score += 5
    return score

df['actual'] = df.apply(f, axis=1)

Если вам нужна более краткая функция, она также будет работать:

def f2(row):
    score = 25
    if pd.isnull(row['address1']) or pd.isnull(row['address2']):
        score -= 10
    score -= row[['city', 'country', 'county']].isnull().sum() * 5
    return score

Более эффективным:

bool_arr = df.isna().values
score = np.where(np.any(bool_arr[:,0:2], 1), 0, 10)
score += np.sum(~bool_arr[:,2:5], 1) * 5
df['score'] = score
1
Oliver Scott 1 Июл 2019 в 15:51

Как насчет этого:

In [31]:df_boolean = df.notna()
        df_boolean['add1&add2'] = (df_boolean.loc[:,['address1','address2']].all(1))*2
        df_boolean.drop(['address1','address2'], axis=1, inplace=True)
        df_boolean = df_boolean * 5
        df_boolean['score'] = df_boolean.sum(axis=1)



In [32]: df_boolean
Out[32]: 
  city country county  add1&add2  score
0    5       5      5         10   25.0
1    0       5      5         10   20.0
2
Mark 1 Июл 2019 в 11:30

Просто чтобы добавить другой метод:

d={"address1":10,"address2":10,"city":5,"country":5,"county":5} #ref dict
other_address=['city','country','county'] #other address columns
address = df.columns.difference(other_address) #primary address columns

Объединение путем проверки любого Nan в адресных столбцах и другого df без адресных столбцов:

m=pd.concat([pd.Series(df[address].notna().all(axis=1),name='address1'),
         df[other_address].notna()],axis=1)
print(m)

   address1   city  country  county
0      True   True     True    True
1      True  False     True    True

Затем с помощью df.dot() и dict.get()

(m.dot(m.columns+ ',').str[:-1].str.split(',')
    .apply(lambda x: sum([int(d.get(i)) for i in x])))

0    25
1    20
1
anky_91 1 Июл 2019 в 12:38