Python / Pandas: используйте функцию поиска DataFrame + для замены определенных / нулевых значений в DataFrame - PullRequest
4 голосов
/ 08 апреля 2020

Скажем, у меня есть неполный набор данных в Pandas DataFrame, например:

incData  = pd.DataFrame({'comp': ['A']*3 + ['B']*5 + ['C']*4,
                         'x': [1,2,3] + [1,2,3,4,5] + [1,2,3,4],
                         'y': [3,None,7] + [1,4,7,None,None] + [4,None,2,1]})

, а также DataFrame с подходящими параметрами, которые я мог бы использовать для заполнения отверстий:

fitTable = pd.DataFrame({'slope': [2,3,-1],
                         'intercept': [1,-2,5]},
                         index=['A','B','C'])

Я хотел бы добиться следующего, используя y = x * slope + intercept только для записей None:

   comp  x     y
0     A  1   3.0
1     A  2   5.0
2     A  3   7.0
3     B  1   1.0
4     B  2   4.0
5     B  3   7.0
6     B  4  10.0
7     B  5  13.0
8     C  1   4.0
9     C  2   3.0
10    C  3   2.0
11    C  4   1.0

Один из способов, который я предполагал, - это использовать join и drop:

incData = incData.join(fitTable,on='comp')
incData.loc[incData['y'].isnull(),'y'] = incData[incData['y'].isnull()]['x']*\
                                         incData[incData['y'].isnull()]['slope']+\
                                         incData[incData['y'].isnull()]['intercept']
incData.drop(['slope','intercept'], axis=1, inplace=True)

Тем не менее, это не очень эффективно, потому что добавляет и удаляет столбцы. Кажется, я делаю это слишком сложным, я пропускаю простое, более прямое решение? Нечто похожее на этот нефункциональный код:

incData.loc[incData['y'].isnull(),'y'] = incData[incData['y'].isnull()]['x']*\
                                         fitTable[incData[incData['y'].isnull()]['comp']]['slope']+\
                                         fitTable[incData[incData['y'].isnull()]['comp']]['intercept']

Я довольно новичок в Pandas, поэтому иногда меня смешивают строгие правила индексации ...

Ответы [ 3 ]

1 голос
/ 08 апреля 2020

Вы можете использовать map в столбце 'comp', маскируя его с нулевым значением в 'y', например:

mask = incData['y'].isna()
incData.loc[mask, 'y'] = incData.loc[mask, 'x']*\
                         incData.loc[mask,'comp'].map(fitTable['slope']) +\
                         incData.loc[mask,'comp'].map(fitTable['intercept'])

и вашим нефункциональным кодом, я думаю, это будет что-то вроде:

incData.loc[mask,'y'] = incData.loc[mask, 'x']*\
                        fitTable.loc[incData.loc[mask, 'comp'],'slope'].to_numpy()+\
                        fitTable.loc[incData.loc[mask, 'comp'],'intercept'].to_numpy()
1 голос
/ 08 апреля 2020

IIU C:

incData.loc[pd.isna(incData['y']), 'y'] = incData[pd.isna(incData['y'])].apply(lambda row: row['x']*fitTable.loc[row['comp'], 'slope']+fitTable.loc[row['comp'], 'intercept'], axis=1)

incData
comp  x     y
0     A  1   3.0
1     A  2   5.0
2     A  3   7.0
3     B  1   1.0
4     B  2   4.0
5     B  3   7.0
6     B  4  10.0
7     B  5  13.0
8     C  1   4.0
9     C  2   3.0
10    C  3   2.0
11    C  4   1.0

0 голосов
/ 08 апреля 2020

merge другой вариант

# merge two dataframe together on comp
m = incData.merge(fitTable, left_on='comp', right_index=True)
# y = mx+b
m['y'] = m['x']*m['slope']+m['intercept']

   comp  x   y  slope  intercept
0     A  1   3      2          1
1     A  2   5      2          1
2     A  3   7      2          1
3     B  1   1      3         -2
4     B  2   4      3         -2
5     B  3   7      3         -2
6     B  4  10      3         -2
7     B  5  13      3         -2
8     C  1   4     -1          5
9     C  2   3     -1          5
10    C  3   2     -1          5
11    C  4   1     -1          5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...