Панды - рассчитать среднее значение столбцов с условием на основе значений в других столбцах - PullRequest
1 голос
/ 21 марта 2019

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

ID, 1_a, 1_b, 1_c, 2_a, 2_b, 2_c, 3_a, 3_b, 3_c 
0, 0, 145, 0.8, 0, 555, 0.7, 1, 335, 0.7
1, 1, 222, 0.9, 1, 224, 0.4, 1, 555, 0.6
3, 1, 111, 0.3, 0, 222, 0.5, 1, 999, 0.7 

Я надеюсь получить следующий результат:

ID, 1_a, 1_b, 1_c, 2_a, 2_b, 2_c, 3_a, 3_b, 3_c, NEW
0, 0, 145, 0.8, 0, 555, 0.7, 1, 335, 0.7, 0.7
1, 1, 222, 0.8, 1, 224, 0.4, 1, 555, 0.6, 0.6
3, 1, 111, 0.3, 0, 222, 0.5, 1, 999, 0.7, 0.5

Логика следующая.

If 1_a is 1, keep value in 1_c, if not ignore
If 2_a is 1, keep value in 2_c, if not ignore
If 3_a is 1, keep value in 3_c, if not ignore

рассчитать среднее значение сохраненных значений для каждой строки и сохранить в столбце 'NEW'

Я пробовал несколько способов, но это работает, только если у меня есть только 1 строка во фрейме данных. Если у меня есть более 1 строки, кажется, что рассчитать среднее значение для всего фрейма данных. Кроме того, я пытаюсь оптимизировать функцию, поскольку у меня есть более 10 из этих условий ЕСЛИ. Это то, что я пытался, но это не дает мне результат, я ищу:

 def test(x):
    a = x[x['1_a']==1]['1_c'].values
    b = x[x['2_a']==1]['2_c'].values
    c = x[x['3_a']==1]['3_c'].values
    xx =np.concatenate((a,b,c), axis=0)
    z = sum(xx)/len(xx)
    x['New_Prob'] = z
    return x
print(test(df))

Результат примерно такой:

ID, 1_a, 1_b, 1_c, 2_a, 2_b, 2_c, 3_a, 3_b, 3_c, NEW
0, 0, 145, 0.8, 0, 555, 0.7, 1, 335, 0.7, 0.6
1, 1, 222, 0.8, 1, 224, 0.4, 1, 555, 0.6, 0.6
3, 1, 111, 0.3, 0, 222, 0.5, 1, 999, 0.7, 0.6

Ответы [ 3 ]

1 голос
/ 21 марта 2019

Вы можете упростить это, написав for loop, который проходит через каждый столбец с суффиксами _c и _a и условно заменяет значения на NaN, используя np.where.

В конце вы создаете столбец NEW, используя pandas.DataFrame.mean

# First we remove the spaces from your column names
df.columns = df.columns.str.strip()

amt_cols_check = 3

for x in range(amt_cols_check):
    df[f'{x+1}_c'] = np.where(df[f'{x+1}_a'] == 1, df[f'{x+1}_c'], np.NaN)

cols_mean = [col for col in df.columns if col.endswith('_c')]
df['NEW'] =  round(df[cols_mean].mean(axis=1), 1)

print(df)
   ID  1_a  1_b  1_c  2_a  2_b  2_c  3_a  3_b  3_c  NEW
0   0    0  145  NaN    0  555  NaN    1  335  0.7  0.7
1   1    1  222  0.9    1  224  0.4    1  555  0.6  0.6
2   3    1  111  0.3    0  222  NaN    1  999  0.7  0.5

примечание , как отметил AlexK в комментариях. В своем ответе я использую f-strings, которые поддерживаются только в Python 3.6 и более поздних версиях.

0 голосов
/ 21 марта 2019

Вот решение, которое не требует замены существующих значений в кадре данных чем-либо, но предполагает, что в столбцах _a есть только 1 и 0.

Эта проблема по существу становится средневзвешенным значениемстолбцы "_c", взвешенные по столбцам "_a".

df.columns = df.columns.str.strip()

a_cols = [col for col in df.columns if col.endswith('_a')]
c_cols = [col for col in df.columns if col.endswith('_c')]
#create a list of tuples of column names, i.e., [('1_a', '1_c'), ('2_a', '2_c'), ('3_a', '3_c')]
a_c = list(zip(a_cols,c_cols)) #if using Python 2.x, use zip(a_cols,c_cols)

df['NEW'] = sum([df[x] * df[y] for x,y in a_c]) / sum([df[z] for z in a_cols])
0 голосов
/ 21 марта 2019

Если ваши столбцы находятся в одинаковом диапазоне для «_a» и «_c», вы можете просто просмотреть их;

r = range(1,4)
for i in r:
    df.loc[df["{}_a".format(i)] != 1, "{}_c".format(i)] = np.NaN

df['NEW'] = df[['{}_c'.format(i) for i in r]].mean(axis=1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...