gpt4 book ai didi

r - 如何基于 data.table 中的分类变量以编程方式创建二进制列?

转载 作者:行者123 更新时间:2023-12-04 10:57:49 24 4
gpt4 key购买 nike

我有一个很大的(1200 万行)data.table,如下所示:

library(data.table)
set.seed(123)
dt <- data.table(id=rep(1:3, each=5),y=sample(letters[1:5],15,replace = T))
> dt
id y
1: 1 b
2: 1 d
3: 1 c
4: 1 e
5: 1 e
6: 2 a
7: 2 c
8: 2 e
9: 2 c
10: 2 c
11: 3 e
12: 3 c
13: 3 d
14: 3 c
15: 3 a

我想创建一个新的 data.table 包含我的变量 id (这将是这个新的 data.table 的唯一键) 和其他 5 个二进制变量,每个对应于 y 的每个类别,如果 id 具有 y 的值,则取值 10 否则。
输出 data.table 应该如下所示:

   id a b c d e
1: 1 0 1 1 1 1
2: 2 1 0 1 0 1
3: 3 1 0 1 1 1

我尝试在循环中执行此操作,但速度很慢,而且我不知道如何以编程方式传递二进制变量名称,因为它们取决于我尝试“拆分”的变量。

编辑:正如@mtoto 指出的那样,已经提出并回答了类似的问题here ,但解决方案是使用 reshape2 包。
我想知道是否有另一种(更快的)方法可以通过在 data.table 中使用 := 运算符来做到这一点,因为我有一个庞大的数据集并且我正在使用这个包进行大量工作。

EDIT2:@Arun 关于我的数据的帖子中的函数基准(约 1200 万行,约 350 万个不同的 ID 和 490 个不同的 y 标签变量(产生 490 个虚拟变量):

system.time(ans1 <- AnsFunction())   # 194s
system.time(ans2 <- dcastFunction()) # 55s
system.time(ans3 <- TableFunction()) # Takes forever and blocked my PC

最佳答案

data.table 有自己的 dcast 实现,使用 data.table 的内部结构,应该很快。试一试:

dcast(dt, id ~ y, fun.aggregate = function(x) 1L, fill=0L)
# id a b c d e
# 1: 1 0 1 1 1 1
# 2: 2 1 0 1 0 1
# 3: 3 1 0 1 1 1

只是想到了另一种方法来通过引用预分配和更新来处理这个问题(也许 dcast 的逻辑应该这样做以避免中间体)。

ans = data.table(id = unique(dt$id))[, unique(dt$y) := 0L][]

剩下的就是用 1L 填充现有组合。

dt[, {set(ans, i=.GRP, j=unique(y), value=1L); NULL}, by=id]
ans
# id b d c e a
# 1: 1 1 1 1 1 0
# 2: 2 0 0 1 1 1
# 3: 3 0 1 1 1 1

好的,我已经在 OP 的数据维度上进行了基准测试,大约有 1000 万行和 10 列。

require(data.table)
set.seed(45L)
y = apply(matrix(sample(letters, 10L*20L, TRUE), ncol=20L), 1L, paste, collapse="")
dt = data.table(id=sample(1e5,1e7,TRUE), y=sample(y,1e7,TRUE))

system.time(ans1 <- AnsFunction()) # 2.3s
system.time(ans2 <- dcastFunction()) # 2.2s
system.time(ans3 <- TableFunction()) # 6.2s

setcolorder(ans1, names(ans2))
setcolorder(ans3, names(ans2))
setorder(ans1, id)
setkey(ans2, NULL)
setorder(ans3, id)

identical(ans1, ans2) # TRUE
identical(ans1, ans3) # TRUE

在哪里,

AnsFunction <- function() {
ans = data.table(id = unique(dt$id))[, unique(dt$y) := 0L][]
dt[, {set(ans, i=.GRP, j=unique(y), value=1L); NULL}, by=id]
ans
# reorder columns outside
}

dcastFunction <- function() {
# no need to load reshape2. data.table has its own dcast as well
# no need for setDT
df <- dcast(dt, id ~ y, fun.aggregate = function(x) 1L, fill=0L,value.var = "y")
}

TableFunction <- function() {
# need to return integer results for identical results
# fixed 1 -> 1L; as.numeric -> as.integer
df <- as.data.frame.matrix(table(dt$id, dt$y))
df[df > 1L] <- 1L
df <- cbind(id = as.integer(row.names(df)), df)
setDT(df)
}

关于r - 如何基于 data.table 中的分类变量以编程方式创建二进制列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37742212/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com