我正在清理不同格式的多年数据。我的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的回答所示。