R:如果另一行数组满足条件,则对一个行数组求和,例如excel,但在R中
R: Sum one row array if another row array satisfies conditions, like excel, but in R
比如说,我有 5 个人的数据 A:E。
这些人提供了他们愿意在四个范围内以什么价格购买多少数量的信息。数据采用宽格式。
df = cbind.data.frame(Q1 = c(90,50,20,10,10), Q2 = c(110,0,0,0,0),
Q3 = c(60,60,50,20,5), Q4 = c(20,10,0,0,0),
P1 = 2:6, P2 = c(3,6,8,9,10),
P3 = c(2,3,5,7,9), P4 = 1:5)
row.names(df) = LETTERS[1:5]
(我的实际数据集有很多关于个人在很多时间段的观察,并且有更多的波段)。
我想做的是计算每个人在特定价格类别内愿意购买的数量。
假设我想对一个人愿意以 0 美元到 5 美元之间的任何价格消费的所有数量求和,对于 5 美元到 10 美元之间的价格类别也是如此。使用 excel 我会使用一个简单的 'sumifs' 来做到这一点。
我如何在 R 中执行此操作?
我期望从上面的数据得到的输出是:
0<P<=5 5<P<=10
A 280 0
B 120 0
C 70 0
D 10 20
E 0 15
我通常最近一直在使用 data.table,所以如果有人知道使用这个包的解决方案就更好了。我也尝试过通过重塑数据来做到这一点,但它变得太大而无法处理(警告消息等)所以它需要保持这种格式。
谢谢!
我复制了你的数据集,应该是这样的:
df = cbind.data.frame(Q1 = c(90,50,20,10,10), Q2 = c(110,0,0,0,0),
Q3 = c(60,60,50,20,5), Q4 = c(20,10,0,0,0),
P1 = 2:6, P2 = c(3,6,8,9,10),
P3 = c(2,3,5,7,9), P4 = 1:5)
row.names(df) = LETTERS[1:5]
请始终以易于使用的方式共享您的数据,请参阅 here for ideas.
现在你不需要 data.table(但肯定会有 data.table 方法来做到这一点),我将在这里向你展示一个基本的 R 解决方案:
df.q = df[,1:4]
df.p = df[,5:8]
我在这里将您的数据框分为价格和需求。由于它们具有相同的格式,因此您可以在满足条件的索引上使用 num sum
:
编辑:更新您的问题后,这是基本的 R 解决方案:
sapply(1:5, function(x) sum(cbind(0, df.q[x, df.p[x,] <= 5])))
sapply(1:5, function(x) sum(cbind(0, df.q[x, df.p[x,] > 5 & df.p[x,] <= 10])))
结果是:
> df.q
Q1 Q2 Q3 Q4
A 90 110 60 20
B 50 0 60 10
C 20 0 50 0
D 10 0 20 0
E 10 0 5 0
> df.p
P1 P2 P3 P4
A 2 3 2 1
B 3 6 3 2
C 4 8 5 3
D 5 9 7 4
E 6 10 9 5
> sapply(1:5, function(x) sum(cbind(0, df.q[x, df.p[x,] <= 5])))
[1] 280 120 70 10 0
> sapply(1:5, function(x) sum(cbind(0, df.q[x, df.p[x,] > 5 & df.p[x,] <= 10])))
[1] 0 0 0 20 15
我们分别对以 'Q' 开头的列和以 'P' 开头的列进行子集,以创建两个数据集('dfQ'、'dfP')。然后,我们得到一个逻辑矩阵 ((dfP > 0 & dfP <=5)
, (dfP > 5 & dfP <=10)
),并将它与 'dfQ' 数据集相乘 (*
)。逻辑矩阵中的 TRUE/FALSE
值将被强制转换为 1/0
整数值,因此 'dfQ' 对应于 FALSE/0
的元素在乘法后将为 0,而那些对应于 TRUE/1
逻辑矩阵中的元素将保持不变。然后,我们执行 rowSums
以获得预期的输出。
dfQ <- df[grep('^Q', names(df))]
dfP <- df[grep('^P', names(df))]
Sum0_5 <- rowSums(dfQ*(dfP > 0 & dfP <=5))
Sum5_10 <- rowSums(dfQ*(dfP > 5 & dfP <=10))
cbind(Sum0_5, Sum5_10)
# Sum0_5 Sum5_10
#A 280 0
#B 120 0
#C 70 0
#D 10 20
#E 0 15
比如说,我有 5 个人的数据 A:E。 这些人提供了他们愿意在四个范围内以什么价格购买多少数量的信息。数据采用宽格式。
df = cbind.data.frame(Q1 = c(90,50,20,10,10), Q2 = c(110,0,0,0,0),
Q3 = c(60,60,50,20,5), Q4 = c(20,10,0,0,0),
P1 = 2:6, P2 = c(3,6,8,9,10),
P3 = c(2,3,5,7,9), P4 = 1:5)
row.names(df) = LETTERS[1:5]
(我的实际数据集有很多关于个人在很多时间段的观察,并且有更多的波段)。
我想做的是计算每个人在特定价格类别内愿意购买的数量。
假设我想对一个人愿意以 0 美元到 5 美元之间的任何价格消费的所有数量求和,对于 5 美元到 10 美元之间的价格类别也是如此。使用 excel 我会使用一个简单的 'sumifs' 来做到这一点。
我如何在 R 中执行此操作?
我期望从上面的数据得到的输出是:
0<P<=5 5<P<=10
A 280 0
B 120 0
C 70 0
D 10 20
E 0 15
我通常最近一直在使用 data.table,所以如果有人知道使用这个包的解决方案就更好了。我也尝试过通过重塑数据来做到这一点,但它变得太大而无法处理(警告消息等)所以它需要保持这种格式。
谢谢!
我复制了你的数据集,应该是这样的:
df = cbind.data.frame(Q1 = c(90,50,20,10,10), Q2 = c(110,0,0,0,0),
Q3 = c(60,60,50,20,5), Q4 = c(20,10,0,0,0),
P1 = 2:6, P2 = c(3,6,8,9,10),
P3 = c(2,3,5,7,9), P4 = 1:5)
row.names(df) = LETTERS[1:5]
请始终以易于使用的方式共享您的数据,请参阅 here for ideas.
现在你不需要 data.table(但肯定会有 data.table 方法来做到这一点),我将在这里向你展示一个基本的 R 解决方案:
df.q = df[,1:4]
df.p = df[,5:8]
我在这里将您的数据框分为价格和需求。由于它们具有相同的格式,因此您可以在满足条件的索引上使用 num sum
:
编辑:更新您的问题后,这是基本的 R 解决方案:
sapply(1:5, function(x) sum(cbind(0, df.q[x, df.p[x,] <= 5])))
sapply(1:5, function(x) sum(cbind(0, df.q[x, df.p[x,] > 5 & df.p[x,] <= 10])))
结果是:
> df.q
Q1 Q2 Q3 Q4
A 90 110 60 20
B 50 0 60 10
C 20 0 50 0
D 10 0 20 0
E 10 0 5 0
> df.p
P1 P2 P3 P4
A 2 3 2 1
B 3 6 3 2
C 4 8 5 3
D 5 9 7 4
E 6 10 9 5
> sapply(1:5, function(x) sum(cbind(0, df.q[x, df.p[x,] <= 5])))
[1] 280 120 70 10 0
> sapply(1:5, function(x) sum(cbind(0, df.q[x, df.p[x,] > 5 & df.p[x,] <= 10])))
[1] 0 0 0 20 15
我们分别对以 'Q' 开头的列和以 'P' 开头的列进行子集,以创建两个数据集('dfQ'、'dfP')。然后,我们得到一个逻辑矩阵 ((dfP > 0 & dfP <=5)
, (dfP > 5 & dfP <=10)
),并将它与 'dfQ' 数据集相乘 (*
)。逻辑矩阵中的 TRUE/FALSE
值将被强制转换为 1/0
整数值,因此 'dfQ' 对应于 FALSE/0
的元素在乘法后将为 0,而那些对应于 TRUE/1
逻辑矩阵中的元素将保持不变。然后,我们执行 rowSums
以获得预期的输出。
dfQ <- df[grep('^Q', names(df))]
dfP <- df[grep('^P', names(df))]
Sum0_5 <- rowSums(dfQ*(dfP > 0 & dfP <=5))
Sum5_10 <- rowSums(dfQ*(dfP > 5 & dfP <=10))
cbind(Sum0_5, Sum5_10)
# Sum0_5 Sum5_10
#A 280 0
#B 120 0
#C 70 0
#D 10 20
#E 0 15