如何使用 apply() 系列来识别跨行最大值的列名
How to use the apply() family to identify column names of max values across rows
我想向数据框添加一列,说明在数据框中跨行计算的最大值所在的那些列的名称。
假设我有这个数据框:
set.seed(123)
df <- data.frame(
V1 = rnorm(10),
V2 = rnorm(10),
V3 = rnorm(10)
)
现在要创建一个新列来标识每行的最大值,我使用 apply
:
df$Max <- apply(df[, 1:3], 1, max, na.rm = TRUE)
效果很好:
df
V1 V2 V3 Max
1 -0.56047565 1.2240818 -1.0678237 1.2240818
2 -0.23017749 0.3598138 -0.2179749 0.3598138
3 1.55870831 0.4007715 -1.0260044 1.5587083
4 0.07050839 0.1106827 -0.7288912 0.1106827
5 0.12928774 -0.5558411 -0.6250393 0.1292877
6 1.71506499 1.7869131 -1.6866933 1.7869131
7 0.46091621 0.4978505 0.8377870 0.8377870
8 -1.26506123 -1.9666172 0.1533731 0.1533731
9 -0.68685285 0.7013559 -1.1381369 0.7013559
10 -0.44566197 -0.4727914 1.2538149 1.2538149
现在是困难的部分:我想添加另一列,命名最大值所在的列。到目前为止我已经尝试过的是这个扩展的 apply
statement:
df$Location <- apply(df[, 1:3], 1, function(x) names(x[match(df[,4], x)]))
它似乎确实捕获了名字,但它把它们分散在大量额外的列中:
df
V1 V2 V3 Max Location.1 Location.2 Location.3 Location.4 Location.5
1 -0.56047565 1.2240818 -1.0678237 1.2240818 V2 <NA> <NA> <NA> <NA>
2 -0.23017749 0.3598138 -0.2179749 0.3598138 <NA> V2 <NA> <NA> <NA>
3 1.55870831 0.4007715 -1.0260044 1.5587083 <NA> <NA> V1 <NA> <NA>
4 0.07050839 0.1106827 -0.7288912 0.1106827 <NA> <NA> <NA> V2 <NA>
5 0.12928774 -0.5558411 -0.6250393 0.1292877 <NA> <NA> <NA> <NA> V1
6 1.71506499 1.7869131 -1.6866933 1.7869131 <NA> <NA> <NA> <NA> <NA>
7 0.46091621 0.4978505 0.8377870 0.8377870 <NA> <NA> <NA> <NA> <NA>
8 -1.26506123 -1.9666172 0.1533731 0.1533731 <NA> <NA> <NA> <NA> <NA>
9 -0.68685285 0.7013559 -1.1381369 0.7013559 <NA> <NA> <NA> <NA> <NA>
10 -0.44566197 -0.4727914 1.2538149 1.2538149 <NA> <NA> <NA> <NA> <NA>
Location.6 Location.7 Location.8 Location.9 Location.10
1 <NA> <NA> <NA> <NA> <NA>
2 <NA> <NA> <NA> <NA> <NA>
3 <NA> <NA> <NA> <NA> <NA>
4 <NA> <NA> <NA> <NA> <NA>
5 <NA> <NA> <NA> <NA> <NA>
6 V2 <NA> <NA> <NA> <NA>
7 <NA> V3 <NA> <NA> <NA>
8 <NA> <NA> V3 <NA> <NA>
9 <NA> <NA> <NA> V2 <NA>
10 <NA> <NA> <NA> <NA> V3
如何才能将名字整齐地收集在一列中df$Location
?
我们可以使用max.col
df$Location <- names(df)[1:3][max.col(df[1:3], 'first')]
如果我们想使用apply
apply(df[1:3], 1, function(x) names(x)[which.max(x)])
或者如果它需要匹配 'max' 列,使用 ==
,然后子集 names
apply(df, 1, function(x) names(x)[1:3][x[-length(x)] == x[length(x)]])
在 OP 的代码中,它只循环前 3 列的行,而 match
是在每一行的整个第 4 列上完成的
apply(df[, 1:3], 1, function(x) match(x, df[,4]))
因为有 3 个元素,所以会产生 3 行。在 OP 的代码中,参数是相反的,因此,每行的长度等于 nrow
我想向数据框添加一列,说明在数据框中跨行计算的最大值所在的那些列的名称。
假设我有这个数据框:
set.seed(123)
df <- data.frame(
V1 = rnorm(10),
V2 = rnorm(10),
V3 = rnorm(10)
)
现在要创建一个新列来标识每行的最大值,我使用 apply
:
df$Max <- apply(df[, 1:3], 1, max, na.rm = TRUE)
效果很好:
df
V1 V2 V3 Max
1 -0.56047565 1.2240818 -1.0678237 1.2240818
2 -0.23017749 0.3598138 -0.2179749 0.3598138
3 1.55870831 0.4007715 -1.0260044 1.5587083
4 0.07050839 0.1106827 -0.7288912 0.1106827
5 0.12928774 -0.5558411 -0.6250393 0.1292877
6 1.71506499 1.7869131 -1.6866933 1.7869131
7 0.46091621 0.4978505 0.8377870 0.8377870
8 -1.26506123 -1.9666172 0.1533731 0.1533731
9 -0.68685285 0.7013559 -1.1381369 0.7013559
10 -0.44566197 -0.4727914 1.2538149 1.2538149
现在是困难的部分:我想添加另一列,命名最大值所在的列。到目前为止我已经尝试过的是这个扩展的 apply
statement:
df$Location <- apply(df[, 1:3], 1, function(x) names(x[match(df[,4], x)]))
它似乎确实捕获了名字,但它把它们分散在大量额外的列中:
df
V1 V2 V3 Max Location.1 Location.2 Location.3 Location.4 Location.5
1 -0.56047565 1.2240818 -1.0678237 1.2240818 V2 <NA> <NA> <NA> <NA>
2 -0.23017749 0.3598138 -0.2179749 0.3598138 <NA> V2 <NA> <NA> <NA>
3 1.55870831 0.4007715 -1.0260044 1.5587083 <NA> <NA> V1 <NA> <NA>
4 0.07050839 0.1106827 -0.7288912 0.1106827 <NA> <NA> <NA> V2 <NA>
5 0.12928774 -0.5558411 -0.6250393 0.1292877 <NA> <NA> <NA> <NA> V1
6 1.71506499 1.7869131 -1.6866933 1.7869131 <NA> <NA> <NA> <NA> <NA>
7 0.46091621 0.4978505 0.8377870 0.8377870 <NA> <NA> <NA> <NA> <NA>
8 -1.26506123 -1.9666172 0.1533731 0.1533731 <NA> <NA> <NA> <NA> <NA>
9 -0.68685285 0.7013559 -1.1381369 0.7013559 <NA> <NA> <NA> <NA> <NA>
10 -0.44566197 -0.4727914 1.2538149 1.2538149 <NA> <NA> <NA> <NA> <NA>
Location.6 Location.7 Location.8 Location.9 Location.10
1 <NA> <NA> <NA> <NA> <NA>
2 <NA> <NA> <NA> <NA> <NA>
3 <NA> <NA> <NA> <NA> <NA>
4 <NA> <NA> <NA> <NA> <NA>
5 <NA> <NA> <NA> <NA> <NA>
6 V2 <NA> <NA> <NA> <NA>
7 <NA> V3 <NA> <NA> <NA>
8 <NA> <NA> V3 <NA> <NA>
9 <NA> <NA> <NA> V2 <NA>
10 <NA> <NA> <NA> <NA> V3
如何才能将名字整齐地收集在一列中df$Location
?
我们可以使用max.col
df$Location <- names(df)[1:3][max.col(df[1:3], 'first')]
如果我们想使用apply
apply(df[1:3], 1, function(x) names(x)[which.max(x)])
或者如果它需要匹配 'max' 列,使用 ==
,然后子集 names
apply(df, 1, function(x) names(x)[1:3][x[-length(x)] == x[length(x)]])
在 OP 的代码中,它只循环前 3 列的行,而 match
是在每一行的整个第 4 列上完成的
apply(df[, 1:3], 1, function(x) match(x, df[,4]))
因为有 3 个元素,所以会产生 3 行。在 OP 的代码中,参数是相反的,因此,每行的长度等于 nrow