R data.table列名的保留字?

时间:2015-09-06 18:03:58

标签: r data.table reserved-words

我在data.table中找到了一些关于特定列名称的尖锐边缘。我怎样才能避免割伤自己?假设我有一个data.table,有两列,'type'和'value'。

numRows = 100
numTypes = 10
dt = data.table(type=sample(numTypes, numRows, replace=T),
                value=rnorm(numRows))

如果我想快速计算类型== 3的所有行的平均值,那么效果很好:

dt[type==3, mean(value)]
# [1] 0.08086124

但是,如果“不是我的人”出现并决定“类型”对于专栏来说是一个糟糕的名称,那么它应该是一个“类”吗?

setnames(dt, "type", "class")

现在,当我尝试等效操作时,我收到了可怕的错误消息:

dt[class==3, mean(value)]
# Error in setattr(attr(x, "index"), paste(cols, collapse = "__"), o) : 
#  attempt to set invalid 'class' attribute

我预期的行为(OSX上的1.9.4)?我认为它发生是因为'class'是R中的函数名,而data.table内部的东西正在解释它。在括号中包装i子句似乎解决了这个问题:

dt[(class==3), mean(value)]
# [1] 0.08086124

但也许有些情况下这种解决方法也失败了?

在这种情况下,是否存在预计会失败的列名列表?

用户定义的函数或加载的库是否会导致相同的错误?

一般来说,我应该使用哪种更安全的方法吗?

1 个答案:

答案 0 :(得分:2)

这似乎已经解决了。更新您的data.table包。

function print_r_reverse($in) {
    $lines = explode("\n", trim($in));
    if (trim($lines[0]) != 'Array') {
        // bottomed out to something that isn't an array
        return $in;
    } else {
        // this is an array, lets parse it
        if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
            // this is a tested array/recursive call to this function
            // take a set of spaces off the beginning
            $spaces = $match[1];
            $spaces_length = strlen($spaces);
            $lines_total = count($lines);
            for ($i = 0; $i < $lines_total; $i++) {
                if (substr($lines[$i], 0, $spaces_length) == $spaces) {
                    $lines[$i] = substr($lines[$i], $spaces_length);
                }
            }
        }
        array_shift($lines); // Array
        array_shift($lines); // (
        array_pop($lines); // )
        $in = implode("\n", $lines);
        // make sure we only match stuff with 4 preceding spaces (stuff for this array and not a nested one)
        preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
        $pos = array();
        $previous_key = '';
        $in_length = strlen($in);
        // store the following in $pos:
        // array with key = key of the parsed array's item
        // value = array(start position in $in, $end position in $in)
        foreach ($matches as $match) {
            $key = $match[1][0];
            $start = $match[0][1] + strlen($match[0][0]);
            $pos[$key] = array($start, $in_length);
            if ($previous_key != '') $pos[$previous_key][1] = $match[0][1] - 1;
            $previous_key = $key;
        }
        $ret = array();
        foreach ($pos as $key => $where) {
            // recursively see if the parsed out value is an array too
            $ret[$key] = print_r_reverse(substr($in, $where[0], $where[1] - $where[0]));
        }
        return $ret;
    }
}