在具有多个元素的数据表中执行逐行操作
Perform row-wise operation in datatable with multiple elements
我有以下数据table:
library(data.table)
set.seed(1)
DT <- data.table(ind=1:100,x=sample(100),y=sample(100),group=c(rep("A",50),rep("B",50)))
现在我遇到的问题是我需要获取“x”列中的每个值(即每个给定的 ID),并将“y”列中的所有现有值添加到它。我还需要按“组”列单独进行。假设我们从 ID = 1 开始。此元素的值为:x_1 = 68 和 y_1 = 76。我们还看到 y_2 = 39,y_3 = 24等。所以我想计算的是 x_1 + y_1、x_1 + y2、x_1 + y_3 等的总和。但不仅限于x_1,还有 x_2、x_3 等。所以对于 x_2,它看起来像:x_2 + y_1、x_2 + y_2, x_2 + y_3, 等等。这也应该按“组”列单独完成(在这方面,数据集应该简单地按组拆分)。
编辑:仅针对 X_1 和 A 组执行此操作的示例代码:
current_X <- DT[1,x] # not needed, just to illustrate
vector_current_X <- rep(DT[1,x],nrow(DT[group == "A"]))
DT[group == "A",copy_current_X := vector_current_X]
DT[,sum_current_X_Y := copy_current_X + y]
DT
这种方法的一个明显问题是,如果它应用于所有 x,那么最终的 DT 中会添加很多列。所以我不确定这是否是最好的方法。最后,我只是在寻找每个元素 y 和每个组的最低总和(每个元素 x)。
我知道如何按组进行运算,我也知道lapply函数。问题是,根据我的理解,我需要包含一个按行循环。接下来,结果的结构将不同于原始数据 table,因为我们有很多额外的观察结果。我之前看到您可以将列表保存在 data.table 中,但我不确定这是否是最佳方法。我的数据集要大得多,所以效率很重要。
感谢您提供解决此问题的任何提示。
你可以这样做:
DT[, .(.BY$x+DT[group==.BY$group,y]), by=.(x,group)]
每个 x returns N 行,其中 N 是 x 所在组的大小。我们利用特殊的 (.BY
),它在使用 by
时在 j
中可用。基本上,.BY
是一个命名列表,包含分组变量的值。在这里,我将 x (.BY$x
) 的值添加到 DT
子集中的 y
值向量,其中 group
等于当前组值(.BY$group
)
输出:
x group V1
<int> <char> <int>
1: 68 A 144
2: 68 A 107
3: 68 A 92
4: 68 A 121
5: 68 A 160
---
4996: 4 B 25
4997: 4 B 66
4998: 4 B 83
4999: 4 B 27
5000: 4 B 68
您也可以通过连接完成此操作:
DT[,!c("y")][DT[, .(y,group)], on=.(group), allow.cartesian=T][, total:=x+y][order(ind)]
输出:
ind x group y total
<int> <int> <char> <int> <int>
1: 1 68 A 76 144
2: 1 68 A 39 107
3: 1 68 A 24 92
4: 1 68 A 53 121
5: 1 68 A 92 160
---
4996: 100 4 B 21 25
4997: 100 4 B 62 66
4998: 100 4 B 79 83
4999: 100 4 B 23 27
5000: 100 4 B 64 68
如果我理解正确,请求的结果需要一个 cross join,其中 x
的每个元素与 y
的每个元素组合(在每个group
).
这可以使用 CJ()
函数轻松完成:
DT[, CJ(x, y, sorted = FALSE), by = group][, sum_x_y := x + y][]
group x y sum_x_y
1: A 68 76 144
2: A 68 39 107
3: A 68 24 92
4: A 68 53 121
5: A 68 92 160
---
4996: B 4 21 25
4997: B 4 62 66
4998: B 4 79 83
4999: B 4 23 27
5000: B 4 64 68
我有以下数据table:
library(data.table)
set.seed(1)
DT <- data.table(ind=1:100,x=sample(100),y=sample(100),group=c(rep("A",50),rep("B",50)))
现在我遇到的问题是我需要获取“x”列中的每个值(即每个给定的 ID),并将“y”列中的所有现有值添加到它。我还需要按“组”列单独进行。假设我们从 ID = 1 开始。此元素的值为:x_1 = 68 和 y_1 = 76。我们还看到 y_2 = 39,y_3 = 24等。所以我想计算的是 x_1 + y_1、x_1 + y2、x_1 + y_3 等的总和。但不仅限于x_1,还有 x_2、x_3 等。所以对于 x_2,它看起来像:x_2 + y_1、x_2 + y_2, x_2 + y_3, 等等。这也应该按“组”列单独完成(在这方面,数据集应该简单地按组拆分)。
编辑:仅针对 X_1 和 A 组执行此操作的示例代码:
current_X <- DT[1,x] # not needed, just to illustrate
vector_current_X <- rep(DT[1,x],nrow(DT[group == "A"]))
DT[group == "A",copy_current_X := vector_current_X]
DT[,sum_current_X_Y := copy_current_X + y]
DT
这种方法的一个明显问题是,如果它应用于所有 x,那么最终的 DT 中会添加很多列。所以我不确定这是否是最好的方法。最后,我只是在寻找每个元素 y 和每个组的最低总和(每个元素 x)。
我知道如何按组进行运算,我也知道lapply函数。问题是,根据我的理解,我需要包含一个按行循环。接下来,结果的结构将不同于原始数据 table,因为我们有很多额外的观察结果。我之前看到您可以将列表保存在 data.table 中,但我不确定这是否是最佳方法。我的数据集要大得多,所以效率很重要。
感谢您提供解决此问题的任何提示。
你可以这样做:
DT[, .(.BY$x+DT[group==.BY$group,y]), by=.(x,group)]
每个 x returns N 行,其中 N 是 x 所在组的大小。我们利用特殊的 (.BY
),它在使用 by
时在 j
中可用。基本上,.BY
是一个命名列表,包含分组变量的值。在这里,我将 x (.BY$x
) 的值添加到 DT
子集中的 y
值向量,其中 group
等于当前组值(.BY$group
)
输出:
x group V1
<int> <char> <int>
1: 68 A 144
2: 68 A 107
3: 68 A 92
4: 68 A 121
5: 68 A 160
---
4996: 4 B 25
4997: 4 B 66
4998: 4 B 83
4999: 4 B 27
5000: 4 B 68
您也可以通过连接完成此操作:
DT[,!c("y")][DT[, .(y,group)], on=.(group), allow.cartesian=T][, total:=x+y][order(ind)]
输出:
ind x group y total
<int> <int> <char> <int> <int>
1: 1 68 A 76 144
2: 1 68 A 39 107
3: 1 68 A 24 92
4: 1 68 A 53 121
5: 1 68 A 92 160
---
4996: 100 4 B 21 25
4997: 100 4 B 62 66
4998: 100 4 B 79 83
4999: 100 4 B 23 27
5000: 100 4 B 64 68
如果我理解正确,请求的结果需要一个 cross join,其中 x
的每个元素与 y
的每个元素组合(在每个group
).
这可以使用 CJ()
函数轻松完成:
DT[, CJ(x, y, sorted = FALSE), by = group][, sum_x_y := x + y][]
group x y sum_x_y 1: A 68 76 144 2: A 68 39 107 3: A 68 24 92 4: A 68 53 121 5: A 68 92 160 --- 4996: B 4 21 25 4997: B 4 62 66 4998: B 4 79 83 4999: B 4 23 27 5000: B 4 64 68