2016-12-09 7 views
2

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

Subtracting group specific value from rows in pandas

У меня есть кадр данных следующим образом, я хочу, чтобы вычесть другое опорное значение из столбца «Изотропный Shift» в зависимости от которого ядро ​​присутствует (в данном случае C и H, но, в принципе, любое значение из периодической таблицы можно):

REF_H = 30 
REF_C = 180 
df 
    Atom Number Nucleus Isotropic Shift 
0    1  C   49.3721 
1    2  C   52.9650 
2    3  C   36.3443 
3    4  C   50.8163 
4    5  C   50.0493 
5    6  C   49.7985 
6    7  H   24.0772 
7    8  H   23.7986 
8    9  H   24.2922 
9   10  H   24.1632 
10   11  H   24.1572 
11   12  C   102.9401 

Так что я хотел бы, чтобы вернуть столбец дельты, где значение является соответствующей Ref_H или Ref_C значения минус изотропный сдвиг:

modifieddf.tail(2) 
    Atom Number Nucleus Isotropic Shift Delta 
10   11  H   24.1572 5.8428 
11   12  C   102.9401 77.0599 

До сих пор лучшее, что я придумал это:

def generateHandC(df): 
    h = df[df['Nucleus'] == 'H'] 
    h['delta'] = REF_H - h['Isotropic Shift'] 
    c = df[df['Nucleus'] == 'C'] 
    c['delta'] = REF_C - c['Isotropic Shift'] 
    return h, c 

generateHandC(df) 

Output: 
( Atom Number Nucleus Isotropic Shift delta 
6    7  H   24.0772 5.9228 
7    8  H   23.7986 6.2014 
8    9  H   24.2922 5.7078 
9   10  H   24.1632 5.8368 
10   11  H   24.1572 5.8428 
14   15  H   28.3212 1.6788 
15   16  H   28.0110 1.9890 
17   18  H   29.2324 0.7676 
18   19  H   26.7298 3.2702,  Atom Number Nucleus Isotropic Shift  delta 
0    1  C   49.3721 130.6279 
1    2  C   52.9650 127.0350 
2    3  C   36.3443 143.6557 
3    4  C   50.8163 129.1837 
4    5  C   50.0493 129.9507 
5    6  C   49.7985 130.2015 
11   12  C   102.9401 77.0599 
13   14  C   122.3188 57.6812) 

Но это, безусловно, не является оптимальным, он возвращает кадр данных в виде списка и бросает мне SettingWithCopyWarning. В идеале я хочу вернуть исходный фрейм данных плюс дополнительный столбец для значений дельта. Благодаря!

+0

Почему вы не создать эталонное значение столбца вызова и заполнить правильные значения, а затем вы можете дельта столбцы ? Если это часть процесса, создайте функцию для добавления столбца ссылочных значений, затем вычислите delta и затем отпустите столбец. – toasteez

ответ

2

Вы можете map столбец Nucleus по dict, а затем вычитать по sub:

REF_H = 30 
REF_C = 180 
d = {'C': REF_C, 'H':REF_H} 
df['Delta'] = df.Nucleus.map(d).sub(df['Isotropic Shift']) 
print (df) 
    Atom Number Nucleus Isotropic Shift  Delta 
0  0  1  C   49.3721 130.6279 
1  1  2  C   52.9650 127.0350 
2  2  3  C   36.3443 143.6557 
3  3  4  C   50.8163 129.1837 
4  4  5  C   50.0493 129.9507 
5  5  6  C   49.7985 130.2015 
6  6  7  H   24.0772 5.9228 
7  7  8  H   23.7986 6.2014 
8  8  9  H   24.2922 5.7078 
9  9  10  H   24.1632 5.8368 
10 10  11  H   24.1572 5.8428 
11 11  12  C   102.9401 77.0599 
+0

Я собирался использовать заявку, но это намного приятнее –

+0

Спасибо за комментарий! – jezrael

+0

Спасибо, это сработало отлично, и я вижу, что функция карты действительно полезна для меня и в будущем! –

0
df.ix[df.Nucleus == 'H','Reference Value'] = 30 
df.ix[df.Nucleus == 'C','Reference Value'] = 180 

df['delta'] = df['Reference Value'] - df['Isotropic Shift'] 

Atom Number  Nucleus Isotropic Shift Reference Value delta 
1    C   49.3721   180.0    130.6279 
2    C   52.9650   180.0    127.0350 
3    C   36.3443   180.0    143.6557 
4    C   50.8163   180.0    129.1837 
5    C   50.0493   180.0    129.9507 
6    C   49.7985   180.0    130.2015 
7    H   24.0772   30.0    5.9228 
8    H   23.7986   30.0    6.2014 
9    H   24.2922   30.0    5.7078 
10    H   24.1632   30.0    5.8368 
11    H   24.1572   30.0    5.8428 
12    C   102.9401   180.0    77.0599 
Смежные вопросы