【问题标题】:Summing the number of times a value appears in either of 2 columns将值出现在两列中的任意一列中的次数相加
【发布时间】:2017-02-22 23:51:44
【问题描述】:

我有一个大型数据集 - 大约 3200 万行。我有关于电话号码、呼叫来源和目的地的信息。

对于每个电话号码,我想计算它作为 Origin 或 Destination 出现的次数。

示例数据表如下:

library(data.table)
dt <- data.table(Tel=seq(1,5,1), Origin=seq(1,5,1), Destination=seq(3,7,1))

    Tel Origin Destination 
1:   1      1           3 
2:   2      2           4
3:   3      3           5 
4:   4      4           6 
5:   5      5           7 

我有工作代码,但我的数据需要很长时间,因为它涉及 for 循环。如何优化它?

这里是:

for (i in unique(dt$Tel)){
    index <- (dt$Origin == i | dt$Destination == i)
    dt[dt$Tel ==i, "N"] <- sum(index)
}

结果:

    Tel Origin Destination N
1:   1      1           3  1
2:   2      2           4  1
3:   3      3           5  2
4:   4      4           6  2
5:   5      5           7  2

其中 N 表示 Tel=1 出现 1 次,Tel=2 出现 1 次,Tel=3,4 和 5 各出现 2 次。

【问题讨论】:

  • 请注意,问题不是for 循环本身,而是您执行操作的方式。
  • 也许你应该考虑在这里使用图论,使用 igraph 包(电话号码作为节点,呼叫作为有向边)。

标签: r data.table


【解决方案1】:

我们可以做一个meltmatch

dt[, N := melt(dt, id.var = "Tel")[, tabulate(match(value, Tel))]]

或者另一种选择是遍历第 2 列和第 3 列,使用 %in% 检查 'Tel' 中的值是否存在,然后使用 Reduce+ 获取每个 ' 的逻辑元素的总和Tel',将(:=)值分配给'N'

dt[, N := Reduce(`+`, lapply(.SD, function(x) Tel %in% x)), .SDcols = 2:3]
dt
#   Tel Origin Destination N
#1:   1      1           3 1
#2:   2      2           4 1
#3:   3      3           5 2
#4:   4      4           6 2
#5:   5      5           7 2

【讨论】:

  • 但是您的代码产生了以下结果,这是不正确的。我得到了前两个电话号码 N=3 和 N=4,而不是 1,因为它应该是。但我会再检查一次。
  • @RalucaGui 我的代码给出了您在帖子中显示的预期输出
  • 正确,我的错误!代码运行流畅。谢谢!
【解决方案2】:

第二种方法构造一个临时 data.table,然后将其连接到原始数据表。这比 @akrun 的更长且效率可能更低,但可以查看。

# get temporary data.table as the sum of origin and destination frequencies
temp <- setnames(data.table(table(unlist(dt[, .(Origin, Destination)], use.names=FALSE))),
                 c("Tel", "N"))
# turn the variables into integers (Tel is the name of the table above, and thus character)
temp <- temp[, lapply(temp, as.integer)]

现在,加入原来的表

dt <- temp[dt, on="Tel"]
dt
   Tel N Origin Destination
1:   1 1      1           3
2:   2 1      2           4
3:   3 2      3           5
4:   4 2      4           6
5:   5 2      5           7

您可以使用setcolorder获得所需的列顺序

setcolorder(dt, c("Tel", "Origin", "Destination", "N"))

【讨论】:

    猜你喜欢
    • 2015-09-18
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    相关资源
    最近更新 更多