5

我正在研究 R 中的一个相当大的数据集,该数据集分为几个数据帧。

问题是我用整个集合做一些事情,有时我只需要使用或修改集合的一部分并且我的选择器变得非常笨重,fe

aListOfItems$attribute4([aListOfItems$attribute1 == true & aListOfItems$attribute2 == 6
& aListOfItems$attribute3 == "C"),] <- aListOfItems([aListOfItems$attribute1 == true &   
aListOfItems$attribute2 == 6 & aListOfItems$attribute3 == "C"),aListOfItems$attribute5]
* aListOfItems([aListOfItems$attribute1 == true & aListOfItems$attribute2 == 6 &
aListOfItems$attribute3 == "C"),aListOfItems$attribute7]

(这会将所有条目的选定部分的属性 4 设置为 (attribute5 * attribute6) 。)

这很难阅读、理解和编辑。

由于 RAM 的原因,将它们拆分为不同的数据帧并不是一个真正的选择,因为我会定期刷新这些数据并重建所有单独的数据帧也会很痛苦。

那么,有没有办法做类似的事情

items_t6C <- &(aListOfItems([aListOfItems$attribute1 == true & aListOfItems$attribute2
 == 6 & aListOfItems$attribute3 == "C"),]

所以我可以使用

items_t6C$attribute4 <- # do something

或者,也许可以将这样的选择器存储在字符串变量中并使用它?

4

2 回答 2

7

您可以首先构造一个逻辑向量,给它一个有意义的名称,然后在命令中使用它。它使您的脚本更长一点,但更容易阅读:

interesting_bit = with(aListOfItems, attribute1 &   
                                     attribute2 == 6 & 
                                     attribute3 == "C")

此外,使用一点缩进也使代码更具可读性。

aListOfItems$attribute4[interesting_bit,] <- 
     aListOfItems[interesting_bit,aListOfItems$attribute5]
   * aListOfItems[interesting_bit,aListOfItems$attribute7]

并且 usingwithin在可读性方面做得更多:

aListOfItems[interesting_bit,] = within(aListOfItems[interesting_bit,], {
      attribute4 = attribute5 * attribute7
   }

此外,对于逻辑,无需显式测试== true

interesting_bit = aListOfItems$attribute1 &   
         aListOfItems$attribute2 == 6 & aListOfItems$attribute3 == "C"

这最终减少了这一点:

aListOfItems$attribute4([aListOfItems$attribute1 == true & aListOfItems$attribute2 == 6
& aListOfItems$attribute3 == "C"),] <- aListOfItems([aListOfItems$attribute1 == true &   
aListOfItems$attribute2 == 6 & aListOfItems$attribute3 == "C"),aListOfItems$attribute5]
* aListOfItems([aListOfItems$attribute1 == true & aListOfItems$attribute2 == 6 &
aListOfItems$attribute3 == "C"),aListOfItems$attribute7]

对此(注意额外使用with):

interesting_bit = with(aListOfItems, attribute1 &   
                                     attribute2 == 6 & 
                                     attribute3 == "C")
aListOfItems[interesting_bit,] = within(aListOfItems[interesting_bit,], {
      attribute4 = attribute5 * attribute7
   }

这段代码不仅看起来不那么令人生畏,而且还能立即传达出你在做什么,这很难从你的原始代码中推断出来。

于 2013-04-05T09:19:54.347 回答
3

data.table软件包可能对您有用。

data.table主要通过参考工作。特别是在分配和修改列时。尤其是当您达到 RAM 限制时,data.table 的效率非常显着

此外,data.table 已内置到with within by subsetetc 的功能中,使调用更短,代码更易读。

例如,上面的繁琐语句可以简化为:

aDTofItems[attribute1 & attribute2==6 & attribute3=="C", # filter
           attribute4 := attribute5 * attribute6]        # assign

此外,如果您要过滤的属性是key表的属性,那么该行会更短:

aDTofItems[.(TRUE, 6, "C"),     # filter
           attribute4 := attribute5 * attribute6]   # assign

假设每个元素的结构是可比较的,您可以将列表强制转换为 data.table 使用

aDTofItems <- rbindlist(aListOfItems)
# note, if you have factors in your list you should convert them to character before calling rbindlist

# or similarly, although a bit slower 
aDTofItems <- data.table(do.call(rbind, aListOfItems))
于 2013-04-07T20:43:49.153 回答