我有一个包含NaN值的数据框架
df:
score home_odds draw_odds away_odds
0 1:0 59/100 263/100 231/50
1 2:1 24/25 53/20 237/100
2 0:2 221/100 93/50 67/50
3 1:1 259/50 251/100 16/25
.......
1970 NaN 36/25 197/100 47/25
1971 NaN NaN NaN NaN
1972 NaN NaN NaN NaN
1973 NaN NaN NaN NaN
1974 NaN 17/5 263/100 39/50
1975 NaN 77/50 21/10 7/4
1976 NaN 19/50 86/25 691/100
1977 NaN NaN NaN NaN
当我尝试用转换公式
将小数值转换为小数时例句:
123/100 = (123/100 + 1) = 2.23
333/100 = (333/100 +1) = 4.33
计算为分数值+ 1
当然,保留十进制值的代码:
def convert(s):
if '/' in s: # is a fraction
num, den = s.split('/')
return 1 + (int(num) / int(den))
else:
return float(s)
df['home_odds'] = df['home_odds'].apply(convert)
df['away_odds'] = df['away_odds'].apply(convert)
df['draw_odds'] = df['draw_odds'].apply(convert)
我得到错误:
if '/' in s: # is a fraction
TypeError: argument of type 'float' is not iterable
当我删除NaN
值时,公式生效。
我想在数据框中保留NaN
值,只转换非NaN
值。
我该怎么做?
检查在函数开始时数据是否为Nan
(这是float
):
def convert(s):
if pd.isnull(s):
return s
if '/' in s: # is a fraction
num, den = s.split('/')
return 1 + (int(num) / int(den))
else:
return float(s)
与pd.eval
的一个hack。使用str.replace
代替:
59/100
by1+59/100
(结果是1.59)NaN
by1e999-1e999
(结果是NaN)
df.update(df.filter(like='_odds')
.replace({r'(d+)/(d+)': r'1+1/2',
np.NaN: '1e999-1e999'}, regex=True)
.apply(pd.eval))
>>> df
score home_odds draw_odds away_odds
0 1:0 1.59 3.63 5.62
1 2:1 1.96 3.65 3.37
2 0:2 3.21 2.86 2.34
3 1:1 6.18 3.51 1.64
1970 NaN 2.44 2.97 2.88
1971 NaN NaN NaN NaN
1972 NaN NaN NaN NaN
1973 NaN NaN NaN NaN
1974 NaN 4.4 3.63 1.78
1975 NaN 2.54 3.1 2.75
1976 NaN 1.38 4.44 7.91
1977 NaN NaN NaN NaN