Kaggle实战系列之"San Francisco Crime
San Francisco Crime Classification是Kaggle平台上的一项数据分析竞赛,意在通过分析2003到2015的罪案记录,预测在某一时间点可能发生罪案类型。
csv数据文件读取中的一个小坑
利用pandas的read_csv命令读取数据文件是分析数据的第一步。以前从未关注过CSV文件读取时浮点数精度可能发生问题,直到在清洗旧金山犯罪记录分类的数据时,无意中跳进了个小坑。
根据Kaggle给出的数据文件描述,各字段的定义如下:
Dates - timestamp of the crime incident
Category - category of the crime incident (only in train.csv). This is the target variable you are going to predict.
Descript - detailed description of the crime incident (only in train.csv)
DayOfWeek - the day of the week
PdDistrict - name of the Police Department District
Resolution - how the crime incident was resolved (only in train.csv)
Address - the approximate street address of the crime incident
X - Longitude
Y - Latitude
不知何故源文件中的经纬度坐标值,小数点后十几位。觉得没必要就四舍五入保留了6位另存了一份。某次想查询在同一个经纬度坐标下是否会出现不同的地址,发现当想看特定经纬度的数据条时,pandas查询不到。
data = pd.read_csv('./train_new.csv', encoding = "utf-8")
display(data2.query('Lat==37.776540').head(n=1))
而实际上的数据长这样:
打印对应的数据才发现,pandas读取CSV文件时,浮点数的数值已经不声不响给变了。
print("The number is :{}".format(data.query('Lon==-122.417505').Lat.unique()[0]))
结果显示:
The number is : 37.776540000000004
按照pandas.read_csv所述,读取csv文件时,可以通过指定float_precision来指定浮点数的精度,其默认值为'None'。
按命令参数要求,将read_csv命令中的float_precision指定为‘high’或是‘round_trip’后一切正常了。
data = pd.read_csv('./train_new.csv', encoding = "utf-8", float_precision='high')
print("The number is :{}".format(data.query('Lon==-122.417505').Lat.unique()[0]))
display(data.query('Lat==37.776540').head(n=1))
利用csv_read命令读取数据文件时的数字精度的问题难以发现,还与Jupyter Notebook的默认显示精度是小数点后6位有关。对于Lat = 37.776540000000004类似这样的数值,由于csv读取时导致的小数点后n位不是零的情况,平时看到的打印出的数据和csv文件中的数据都正常,但查询时就无法查到数据,也是挺坑人的。这次也是若不是想看下相同坐标下的不同地址,恰巧这条数据排在比较靠前的位置,或许还不知道什么时候才发现。
经此一堑,只觉处处是坑、学无止境。记下一笔,记得提醒自己下次读取CSV文件时,有浮点数的话老老实实加上float_precision可能会少些麻烦。
补记
原以为将float_precision 设为 'high'是最稳妥的,这两天却发现,还是没那么简单。用不同的参数设置读取得到的数据,还是有些许差异。为了对比将pandas的display.precision精度设置为16(实际源文件中X、Y经纬度最长到了坐标小数点后14位)。左上角的trainDF_str是read_csv时指定'X','Y'两列为字符串格式的结果。read_csv默认参数下的结果和float_precision = 'round_trip',以及将字符串转'float64'浮点数的结果相同。
尽管将float_precision设为'high'与按字符串读取其显示的数值不同,但具体查询时仍然可以得到结果。
这样看起来,似乎read_csv时默认参数,不去管这个'float_precision'似乎也不错?
本人还是觉得,没必要为经纬度坐标保留这么多的小数点位数,至少这个犯罪类别分类的问题中不需要。对于本例中,将经纬度坐标保留到小数点后6-7位足够分辨不同记录的发生位置。另,pandas的display.precision默认值为6,平时查看数据时对于小数点后位数更多的数值倒是需要注意下,是否被pandas给自动截尾了。