为什么从字符串转换为整数,然后返回字符串会引发异常



我正在清理不同格式的多年数据。我的DataFrame的年份字段有七个可能的值:['2013-14','2014-15','2015-16','2016-17','22017','22018','22019']。我通过手动处理每个案例解决了这个问题,如下所示:

matchups_df.loc[matchups_df['SEASON_ID'] == '22017', 'SEASON_ID'] = '2017-18'
matchups_df.loc[matchups_df['SEASON_ID'] == '22018', 'SEASON_ID'] = '2018-19'
matchups_df.loc[matchups_df['SEASON_ID'] == '22019', 'SEASON_ID'] = '2019-20'

我的问题是,为什么下面的代码会引发异常ValueError: invalid literal for int() with base 10: '2016-17'?我已经从np.where中删除了相关部分,并在经过过滤的DataFrame版本上使用它来只处理必要的值,但它引发了同样的异常。很明显,在将字符串转换为int时,我已经使用了某种类型的语法eror,但我还没有诊断出错误所在。

matchups_df.insert(loc = 1, column = 'Season', value = (
np.where(
(len(matchups_df.SEASON_ID) == 5),
(
(matchups_df.SEASON_ID[1:]) +
"-" +
(str((matchups_df.SEASON_ID[3:].astype(int))+1))
),
matchups_df.SEASON_ID
)
)
)

这里有必要使用str方法来通过Series.str.len检查长度,并通过str[1:]索引获取第一个值之后的所有值,还因为两个系列都在处理转换为数字。如果没有匹配,则使用to_numeric来避免错误正确的格式:

matchups_df = pd.DataFrame({'SEASON_ID':['2013-14','2014-15','2015-16','2016-17',
'22017','22018','22019'],
'col':range(7)})

print (matchups_df)
SEASON_ID  col
0   2013-14    0
1   2014-15    1
2   2015-16    2
3   2016-17    3
4     22017    4
5     22018    5
6     22019    6

s = matchups_df.SEASON_ID.astype(str)
s1 = np.where(s.str.len() == 5, 
s.str[1:] + "-" + pd.to_numeric(s.str[3:], errors='coerce')
.fillna(0).astype(int).add(1).astype(str), 
matchups_df.SEASON_ID)
matchups_df.insert(loc = 1, column = 'Season', value = s1)
print (matchups_df)
SEASON_ID   Season  col
0   2013-14  2013-14    0
1   2014-15  2014-15    1
2   2015-16  2015-16    2
3   2016-17  2016-17    3
4     22017  2017-18    4
5     22018  2018-19    5
6     22019  2019-20    6

另一个具有自定义功能的解决方案:

def f(x):
if len(x) == 5:
return x[1:] + "-" + str(int(x[3:]) + 1)
else:
return x
s1 = matchups_df.SEASON_ID.astype(str).apply(f)
matchups_df.insert(loc = 1, column = 'Season', value = s1)
print (matchups_df)
SEASON_ID   Season  col
0   2013-14  2013-14    0
1   2014-15  2014-15    1
2   2015-16  2015-16    2
3   2016-17  2016-17    3
4     22017  2017-18    4
5     22018  2018-19    5
6     22019  2019-20    6

此处的根本问题:

matchups_df.SEASON_ID[3:]

matchups_df.SEASON_ID整列(一个系列(。用[3:]切片只会去掉前三行;但是您希望去掉每个值的前三个字符。类似地,len(matchups_df.SEASON_ID) == 5不取决于单元格值(而是取决于的长度(,因此所有单元格(从第四个单元格开始,即五个单元格中的第四个和第五个单元格(最终都会被处理,包括像2016-17这样具有字符串的单元格。

为了获得您想要的行为,提供了.str助手,如@jezrael的回答所示。

最新更新