首页 > 解决方案 > R - 防止数据框列中的数据类型更改

问题描述

如果您在较大的程序中使用数据框作为数据结构,如果预期某种数据类型但在某些其他部分中“意外”更改了数据框列的数据类型,有时会出现错误,这很烦人。

> df=data.frame(x=c(1,2,3))
> typeof(df$x)
[1] "double"
> df$x[1]="a"
> typeof(df$x)
[1] "character"

我想修复列 x 的数据类型,以便分配字符会导致警告或错误。有没有方便的方法呢?

标签: r

解决方案


首先,我同意 DJJ 的评论:最好边看边检查,而不是依赖警告。

但是,正如您所描述的,使用 R 的每个人都可能在某个阶段被意外的类型更改所吸引。

这是发生这种情况时如何实施警告的方法。但请注意:这会带来性能损失,因此它最适合故障排除,并且在您的代码中经常使用可能不是一件好事......

每次将值分配给我们选择的变量时,我们都可以使用“活动绑定”来运行自定义函数。在这种情况下,我们的函数将检查类型是否已更改,如果已更改,则会打印警告。

trackTypeChange = function(x) {
    x_name=x
    makeActiveBinding(x,
        local({ typeofx=""; function(v) {
            if (!missing(v)) {
                if (!all((tov=unlist(lapply(v,typeof)))==typeofx)) {
                    typeofx<<-tov
                    warning(paste("setting type of",x_name,"to",paste(typeofx,collapse=",")),call.=FALSE)
                }
                x<<-v
            } 
            x
        }}),
        .GlobalEnv
    )
}

假设我们要跟踪对 的列类型的无意更改my_tracked_df

trackTypeChange('my_tracked_df')

所以:

my_tracked_df=data.frame(a=1:10,b=1:10+0.1,c=letters[1:10])
# Warning message:
# setting type of my_tracked_df to integer,double,integer

my_tracked_df$a=11:20 # no type change, no warning

my_tracked_df$a=21:30+0.1 
# Warning message:
# setting type of my_tracked_df to double,double,integer

但是:存在性能影响(总是检查类型) - 分配速度大约比相同的非跟踪数据帧慢 3 倍:

my_untracked_df=data.frame(a=1:10,b=1:10+0.1,c=letters[1:10])
system.time(for(i in 1:10000){my_tracked_df$b=my_tracked_df$b+0.1})
#   user  system elapsed
#  0.558   0.006   0.563
system.time(for(i in 1:10000){my_untracked_df$b=my_untracked_df$b+0.1})
#   user  system elapsed
#  0.187   0.001   0.187


推荐阅读