【问题标题】:Calculate row-wise maximum计算逐行最大值
【发布时间】:2015-03-06 23:59:00
【问题描述】:

我想新建一列,等于该行所有列的最大值。

这是一个例子:

library(data.table)
data <- data.table(head(iris))
data[ , Species := NULL]
data

   Sepal.Length Sepal.Width Petal.Length Petal.Width
1:          5.1         3.5          1.4         0.2
2:          4.9         3.0          1.4         0.2
3:          4.7         3.2          1.3         0.2
4:          4.6         3.1          1.5         0.2
5:          5.0         3.6          1.4         0.2
6:          5.4         3.9          1.7         0.4

我不能在这里真正使用max 函数,因为它会找到所有列的最大值,例如data[, max_value := max(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width)]。我想要的是这样的:

   Sepal.Length Sepal.Width Petal.Length Petal.Width max_value
1:          5.1         3.5          1.4         0.2       5.1
2:          4.9         3.0          1.4         0.2       4.9
3:          4.7         3.2          1.3         0.2       4.7
4:          4.6         3.1          1.5         0.2       4.6
5:          5.0         3.6          1.4         0.2       5.0
6:          5.4         3.9          1.7         0.4       5.4

【问题讨论】:

  • 我觉得这里的矩阵存储更好,但我认为 data[,mymax:=apply(.SD,1,max)] 将强制转换为矩阵作为中间步骤。

标签: r data.table


【解决方案1】:

我不会保证它的速度,但这至少可以避免强制转换为矩阵:

data[,mymax:=do.call(pmax,.SD)]

【讨论】:

  • 如何从答案中获得第二个最大值、第三个或第 n 个最大值。
  • @Deepesh 我认为所需的方法完全不同。也许您需要搜索更多内容或发布新问题。
【解决方案2】:

使用dplyr 你可以这样做:

library(dplyr)
setDF(data) %>% 
  rowwise() %>% 
  mutate(max = max(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width))

#Source: local data frame [10 x 5]
#Groups: <by row>
#
#   Sepal.Length Sepal.Width Petal.Length Petal.Width max
#1           5.1         3.5          1.4         0.2 5.1
#2           4.9         3.0          1.4         0.2 4.9
#3           4.7         3.2          1.3         0.2 4.7
#4           4.6         3.1          1.5         0.2 4.6
#5           5.0         3.6          1.4         0.2 5.0
#6           5.4         3.9          1.7         0.4 5.4

或者正如@akrun 建议的那样:

setDF(data) %>% mutate(max=pmax(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width))

这比rowwise() 方法快很多

n <- 10e6; nc <- 4; DT <- data.table(replicate(nc,rnorm(n))) 

mbm <- microbenchmark(
  steven = DT %>% rowwise() %>% mutate(V5 = max(V1, V2, V3, V4)),
  frank = DT[,c(.SD,list(do.call(pmax,.SD)))], 
  akrun = DT %>% mutate(V5 = pmax(V1, V2, V3, V4)), times = 25, unit = "relative")

#Unit: relative
#   expr      min        lq      mean   median        uq       max neval cld
# steven 17.93647 18.024734 17.535764 17.42948 17.484920 16.446384    25   b
#  frank  1.00000  1.000000  1.000000  1.00000  1.000000  1.000000    25  a 
#  akrun  1.00220  1.002281  1.013604  1.00240  1.003089  1.001262    25  a 

【讨论】:

  • 你也可以使用pmax,即setDF(data) %&gt;% mutate(max=pmax(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width))
  • @akrun 是的,这是一个更好的选择。
  • 那个情节很简洁;你能包括用来制作它的命令吗?当我删除 setDT\ setDF (我不明白其中包含)和 := (使其与不修改 DT 的 dplyr 行相当)时,性能相似。 n &lt;- 10e6; nc &lt;- 4; DT &lt;- data.table(replicate(nc,rnorm(n))); microbenchmark(frank = DT[,c(.SD,list(do.call(pmax,.SD)))], akrun = DT %&gt;% mutate(V5=pmax(V1, V2, V3, V4)), times = 10);identical(frank,akrun)不知道为什么结果不一样
  • @Frank ggplot 有一个微基准对象的自动绘图方法:autoplot(mbm)
  • 可能会添加已接受答案的性能,因为它显然对我来说效率很低。
【解决方案3】:

使用by=1:nrow(data) 按行“分组”(这使每一行成为自己的组):

data[, max_value:=max(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width), by=1:nrow(data)]

data
   Sepal.Length Sepal.Width Petal.Length Petal.Width max_value
1:          5.1         3.5          1.4         0.2       5.1
2:          4.9         3.0          1.4         0.2       4.9
3:          4.7         3.2          1.3         0.2       4.7
4:          4.6         3.1          1.5         0.2       4.6
5:          5.0         3.6          1.4         0.2       5.0
6:          5.4         3.9          1.7         0.4       5.4

【讨论】:

  • 这是使用by 的聪明方法。谢谢!
猜你喜欢
  • 1970-01-01
  • 2014-03-01
  • 1970-01-01
  • 2019-01-29
  • 2018-12-20
  • 2020-04-07
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
相关资源
最近更新 更多