如何在data.table中提前指定median_duration列为numeric类型?
背景与代码
我正在Datacamp平台学习由Arun Srinivasan和Matt Dowle讲授的《R语言data.table数据处理》课程,使用的版本为bikeshare14 0.1.4和data.table 1.14.8,编写了如下代码:
# Libraries library(data.table) library(bikeshare14) # Data sets batrips <- as.data.table(x = batrips) # Data manipulation batrips[, `:=` (median_duration = median(duration, na.rm = TRUE)), by = .(start_station, end_station)] |> _[,`:=` (trip_category = fcase( median_duration < 600, "short", median_duration >= 600 & median_duration <= 1800, "medium", median_duration > 1800, "long", default = NA))] batrips
警告信息
运行后收到提示:There were 50 or more warnings (use warnings() to see the first 50),查看警告发现均类似:
Group 11 column 'median_duration': 481.500000 (type 'double') at RHS position 1 truncated (precision lost) when assigning to type 'integer'
解决方法
方法1:提前初始化列并指定类型
在分组计算前,先为batrips添加median_duration列并设置为numeric类型,后续赋值时会保留该类型:
# 提前初始化numeric类型的列 batrips[, median_duration := as.numeric(NA)] # 再执行分组计算赋值 batrips[, `:=` (median_duration = median(duration, na.rm = TRUE)), by = .(start_station, end_station)] |> _[,`:=` (trip_category = fcase( median_duration < 600, "short", median_duration >= 600 & median_duration <= 1800, "medium", median_duration > 1800, "long", default = NA))]
方法2:赋值时显式转换结果类型
直接在计算中位数时用as.numeric()包裹结果,确保返回值为numeric类型,避免data.table自动推断为integer:
batrips[, `:=` (median_duration = as.numeric(median(duration, na.rm = TRUE))), by = .(start_station, end_station)] |> _[,`:=` (trip_category = fcase( median_duration < 600, "short", median_duration >= 600 & median_duration <= 1800, "medium", median_duration > 1800, "long", default = NA))]
方法3:事后修改列类型(可选)
如果已经完成赋值操作,可使用setcoltypes()函数修改列类型:
# 先完成原计算 batrips[, `:=` (median_duration = median(duration, na.rm = TRUE)), by = .(start_station, end_station)] |> _[,`:=` (trip_category = fcase( median_duration < 600, "short", median_duration >= 600 & median_duration <= 1800, "medium", median_duration > 1800, "long", default = NA))] # 修改列类型为numeric setcoltypes(batrips, "median_duration", "numeric")
原因说明
警告产生的核心原因是:原duration列是integer类型,当分组计算中位数时,部分组存在偶数个样本,中位数为小数(返回double类型),但data.table默认会尝试将新创建的median_duration列推断为integer类型,导致小数被截断,触发精度丢失警告。通过提前指定或显式转换类型,就能避免这个问题。
内容的提问来源于stack exchange,提问作者luifrancgom

