R 对于每行,返回最大值的列名

R 对于每行,返回最大值的列名,r,R,我有一份员工名册,我需要知道他们最常在哪个部门工作。将员工ID与部门名称制成表格很简单,但从频率表中返回部门名称(而不是花名册计数的数量)更为棘手。下面是一个简单的示例(列名=部门,行名=员工ID) 使用您的数据的一个选项(为了将来的参考,请使用set.seed()使用sample复制示例): …其中方法可以是随机的第一个或最后一个 如果恰好有两个等于最大值的列,这当然会导致问题。我不确定您在该实例中想要做什么,因为对于某些行,您将有多个结果。例如: DF <- data.frame(V1

我有一份员工名册,我需要知道他们最常在哪个部门工作。将员工ID与部门名称制成表格很简单,但从频率表中返回部门名称(而不是花名册计数的数量)更为棘手。下面是一个简单的示例(列名=部门,行名=员工ID)


使用您的数据的一个选项(为了将来的参考,请使用
set.seed()
使用
sample
复制示例):

…其中
方法可以是
随机的
第一个
最后一个

如果恰好有两个等于最大值的列,这当然会导致问题。我不确定您在该实例中想要做什么,因为对于某些行,您将有多个结果。例如:

DF <- data.frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(7,6,4))
apply(DF,1,function(x) which(x==max(x)))

[[1]]
V2 V3 
 2  3 

[[2]]
V1 
 1 

[[3]]
V2 
 2 

DF使用您的数据的一个选项(为了将来的参考,请使用
set.seed()
使用
sample
复制示例):

…其中
方法可以是
随机的
第一个
最后一个

如果恰好有两个等于最大值的列,这当然会导致问题。我不确定您在该实例中想要做什么,因为对于某些行,您将有多个结果。例如:

DF <- data.frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(7,6,4))
apply(DF,1,function(x) which(x==max(x)))

[[1]]
V2 V3 
 2  3 

[[2]]
V1 
 1 

[[3]]
V2 
 2 

DF如果您对
data.table
解决方案感兴趣,这里有一个。这有点棘手,因为您更喜欢获取第一个最大值的id。如果你想要最后一个最大值,那就容易多了。然而,它并没有那么复杂,而且速度很快

这里我已经生成了您的维度数据(26746*18)

资料 标杆管理:
如果您对
data.table
解决方案感兴趣,这里有一个。这有点棘手,因为您更喜欢获取第一个最大值的id。如果你想要最后一个最大值,那就容易多了。然而,它并没有那么复杂,而且速度很快

这里我已经生成了您的维度数据(26746*18)

资料 标杆管理:
基于以上建议,以下
数据表
解决方案对我来说非常有效:

library(data.table)

set.seed(45)
DT <- data.table(matrix(sample(10, 10^7, TRUE), ncol=10))

system.time(
  DT[, col_max := colnames(.SD)[max.col(.SD, ties.method = "first")]]
)
#>    user  system elapsed 
#>    0.15    0.06    0.21
DT[]
#>          V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 col_max
#>       1:  7  4  1  2  3  7  6  6  6   1      V1
#>       2:  4  6  9 10  6  2  7  7  1   3      V4
#>       3:  3  4  9  8  9  9  8  8  6   7      V3
#>       4:  4  8  8  9  7  5  9  2  7   1      V4
#>       5:  4  3  9 10  2  7  9  6  6   9      V4
#>      ---                                       
#>  999996:  4  6 10  5  4  7  3  8  2   8      V3
#>  999997:  8  7  6  6  3 10  2  3 10   1      V6
#>  999998:  2  3  2  7  4  7  5  2  7   3      V4
#>  999999:  8 10  3  2  3  4  5  1  1   4      V2
#> 1000000: 10  4  2  6  6  2  8  4  7   4      V1

如果我们需要@lwshang建议的最小值的列名,只需使用
-.SD

DT[, col_min := colnames(.SD)[max.col(-.SD, ties.method = "first")]]

基于以上建议,以下
数据表
解决方案对我来说非常有效:

library(data.table)

set.seed(45)
DT <- data.table(matrix(sample(10, 10^7, TRUE), ncol=10))

system.time(
  DT[, col_max := colnames(.SD)[max.col(.SD, ties.method = "first")]]
)
#>    user  system elapsed 
#>    0.15    0.06    0.21
DT[]
#>          V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 col_max
#>       1:  7  4  1  2  3  7  6  6  6   1      V1
#>       2:  4  6  9 10  6  2  7  7  1   3      V4
#>       3:  3  4  9  8  9  9  8  8  6   7      V3
#>       4:  4  8  8  9  7  5  9  2  7   1      V4
#>       5:  4  3  9 10  2  7  9  6  6   9      V4
#>      ---                                       
#>  999996:  4  6 10  5  4  7  3  8  2   8      V3
#>  999997:  8  7  6  6  3 10  2  3 10   1      V6
#>  999998:  2  3  2  7  4  7  5  2  7   3      V4
#>  999999:  8 10  3  2  3  4  5  1  1   4      V2
#> 1000000: 10  4  2  6  6  2  8  4  7   4      V1

如果我们需要@lwshang建议的最小值的列名,只需使用
-.SD

DT[, col_min := colnames(.SD)[max.col(-.SD, ties.method = "first")]]

一种解决方案是将日期从宽改为长,将所有部门放在一列中,计数在另一列中,按雇主id(在本例中为行号)分组,然后用最大值过滤到部门。使用这种方法处理关系也有两种选择

library(tidyverse)

# sample data frame with a tie
df <- data_frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(9,6,5))

# If you aren't worried about ties:  
df %>% 
  rownames_to_column('id') %>%  # creates an ID number
  gather(dept, cnt, V1:V3) %>% 
  group_by(id) %>% 
  slice(which.max(cnt)) 

# A tibble: 3 x 3
# Groups:   id [3]
  id    dept    cnt
  <chr> <chr> <dbl>
1 1     V3       9.
2 2     V1       8.
3 3     V2       5.


# If you're worried about keeping ties:
df %>% 
  rownames_to_column('id') %>%
  gather(dept, cnt, V1:V3) %>% 
  group_by(id) %>% 
  filter(cnt == max(cnt)) %>% # top_n(cnt, n = 1) also works
  arrange(id)

# A tibble: 4 x 3
# Groups:   id [3]
  id    dept    cnt
  <chr> <chr> <dbl>
1 1     V3       9.
2 2     V1       8.
3 3     V2       5.
4 3     V3       5.


# If you're worried about ties, but only want a certain department, you could use rank() and choose 'first' or 'last'
df %>% 
  rownames_to_column('id') %>%
  gather(dept, cnt, V1:V3) %>% 
  group_by(id) %>% 
  mutate(dept_rank  = rank(-cnt, ties.method = "first")) %>% # or 'last'
  filter(dept_rank == 1) %>% 
  select(-dept_rank) 

# A tibble: 3 x 3
# Groups:   id [3]
  id    dept    cnt
  <chr> <chr> <dbl>
1 2     V1       8.
2 3     V2       5.
3 1     V3       9.

# if you wanted to keep the original wide data frame
df %>% 
  rownames_to_column('id') %>%
  left_join(
    df %>% 
      rownames_to_column('id') %>%
      gather(max_dept, max_cnt, V1:V3) %>% 
      group_by(id) %>% 
      slice(which.max(max_cnt)), 
    by = 'id'
  )

# A tibble: 3 x 6
  id       V1    V2    V3 max_dept max_cnt
  <chr> <dbl> <dbl> <dbl> <chr>      <dbl>
1 1        2.    7.    9. V3            9.
2 2        8.    3.    6. V1            8.
3 3        1.    5.    5. V2            5.
库(tidyverse)
#带领带的示例数据框
df%
行名到列('id')%>%
聚集(部门,cnt,V1:V3)%>%
分组依据(id)%>%
过滤器(cnt==max(cnt))%>%#top_n(cnt,n=1)也可以工作
安排(id)
#一个tibble:4x3
#组别:id[3]
id部门cnt
1 V3 9。
2 v18。
3 v25。
4 3 V3 5。
#如果您担心领带,但只想要某个部门,可以使用rank()并选择“first”或“last”
df%>%
行名到列('id')%>%
聚集(部门,cnt,V1:V3)%>%
分组依据(id)%>%
变异(dept_rank=rank(-cnt,ties.method=“first”)%>%#或“last”
筛选(部门排名==1)%>%
选择(-dept\u rank)
#一个tibble:3x3
#组别:id[3]
id部门cnt
1 2 v18。
2 3 V2 5。
3 1 V3 9。
#如果要保留原始宽数据帧
df%>%
行名到列('id')%>%
左联合(
df%>%
行名到列('id')%>%
聚集(最大部门,最大控制,V1:V3)%>%
分组依据(id)%>%
切片(哪个.max(max_cnt)),
by='id'
)
#一个tibble:3x6
id V1 V2 V3最大部门最大值
1 1        2.    7.9V39。
2 2        8.    3.6.v18。
3 3        1.    5.5.v25。

一种解决方案是将日期从宽改为长,将所有部门放在一列,计数在另一列,按雇主id(在本例中为行号)分组,然后用最大值过滤到部门。使用这种方法处理关系也有两种选择

library(tidyverse)

# sample data frame with a tie
df <- data_frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(9,6,5))

# If you aren't worried about ties:  
df %>% 
  rownames_to_column('id') %>%  # creates an ID number
  gather(dept, cnt, V1:V3) %>% 
  group_by(id) %>% 
  slice(which.max(cnt)) 

# A tibble: 3 x 3
# Groups:   id [3]
  id    dept    cnt
  <chr> <chr> <dbl>
1 1     V3       9.
2 2     V1       8.
3 3     V2       5.


# If you're worried about keeping ties:
df %>% 
  rownames_to_column('id') %>%
  gather(dept, cnt, V1:V3) %>% 
  group_by(id) %>% 
  filter(cnt == max(cnt)) %>% # top_n(cnt, n = 1) also works
  arrange(id)

# A tibble: 4 x 3
# Groups:   id [3]
  id    dept    cnt
  <chr> <chr> <dbl>
1 1     V3       9.
2 2     V1       8.
3 3     V2       5.
4 3     V3       5.


# If you're worried about ties, but only want a certain department, you could use rank() and choose 'first' or 'last'
df %>% 
  rownames_to_column('id') %>%
  gather(dept, cnt, V1:V3) %>% 
  group_by(id) %>% 
  mutate(dept_rank  = rank(-cnt, ties.method = "first")) %>% # or 'last'
  filter(dept_rank == 1) %>% 
  select(-dept_rank) 

# A tibble: 3 x 3
# Groups:   id [3]
  id    dept    cnt
  <chr> <chr> <dbl>
1 2     V1       8.
2 3     V2       5.
3 1     V3       9.

# if you wanted to keep the original wide data frame
df %>% 
  rownames_to_column('id') %>%
  left_join(
    df %>% 
      rownames_to_column('id') %>%
      gather(max_dept, max_cnt, V1:V3) %>% 
      group_by(id) %>% 
      slice(which.max(max_cnt)), 
    by = 'id'
  )

# A tibble: 3 x 6
  id       V1    V2    V3 max_dept max_cnt
  <chr> <dbl> <dbl> <dbl> <chr>      <dbl>
1 1        2.    7.    9. V3            9.
2 2        8.    3.    6. V1            8.
3 3        1.    5.    5. V2            5.
库(tidyverse)
#带领带的示例数据框
df%
行名到列('id')%>%
聚集(部门,cnt,V1:V3)%>%
分组依据(id)%>%
过滤器(cnt==max(cnt))%>%#top_n(cnt,n=1)也可以工作
安排(id)
#一个tibble:4x3
#组别:id[3]
id部门cnt
1 V3 9。
2 v18。
3 v25。
4 3 V3 5。
#如果您担心领带,但只想要某个部门,可以使用rank()并选择“first”或“last”
df%>%
行名到列('id')%>%
聚集(部门,cnt,V1:V3)%>%
分组依据(id)%>%
变异(dept_rank=rank(-cnt,ties.method=“first”)%>%#或“last”
筛选(部门排名==1)%>%
选择(-dept\u rank)
#一个tibble:3x3
#组别:id[3]
id部门cnt
1 2 v18。
2 3 V2 5。
3 1 V3 9。
#如果要保留原始宽数据帧
df%>%
行名到列('id')%>%
左联合(
df%>%
行名到列('id')%>%
聚集(最大部门,最大控制,V1:V3)%>%
分组依据(id)%>%
切片(哪个.max(max_cnt)),
by='id'
)
#一个tibble:3x6
id V1 V2 V3最大部门最大值
1 1        2.    7.9V39。
2 2        8.    3.6.v18。
3 3        1.    5.5.v25。

一个简单的
for
循环也很方便:

> df<-data.frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(9,6,4))
> df
  V1 V2 V3
1  2  7  9
2  8  3  6
3  1  5  4
> df2<-data.frame()
> for (i in 1:nrow(df)){
+   df2[i,1]<-colnames(df[which.max(df[i,])])
+ }
> df2
  V1
1 V3
2 V1
3 V2
>测向
V1 V2 V3
1  2  7  9
2  8  3  6
3  1  5  4
>df2(1中的i:nrow(df)){
+df2[i,1]df2
V1
1 V3
2 V1
3 V2
一个简单的
library(data.table)

set.seed(45)
DT <- data.table(matrix(sample(10, 10^7, TRUE), ncol=10))

system.time(
  DT[, col_max := colnames(.SD)[max.col(.SD, ties.method = "first")]]
)
#>    user  system elapsed 
#>    0.15    0.06    0.21
DT[]
#>          V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 col_max
#>       1:  7  4  1  2  3  7  6  6  6   1      V1
#>       2:  4  6  9 10  6  2  7  7  1   3      V4
#>       3:  3  4  9  8  9  9  8  8  6   7      V3
#>       4:  4  8  8  9  7  5  9  2  7   1      V4
#>       5:  4  3  9 10  2  7  9  6  6   9      V4
#>      ---                                       
#>  999996:  4  6 10  5  4  7  3  8  2   8      V3
#>  999997:  8  7  6  6  3 10  2  3 10   1      V6
#>  999998:  2  3  2  7  4  7  5  2  7   3      V4
#>  999999:  8 10  3  2  3  4  5  1  1   4      V2
#> 1000000: 10  4  2  6  6  2  8  4  7   4      V1
DT[, MAX2 := colnames(.SD)[max.col(.SD, ties.method="first")], .SDcols = c("V9", "V10")]
DT[, col_min := colnames(.SD)[max.col(-.SD, ties.method = "first")]]
library(tidyverse)

# sample data frame with a tie
df <- data_frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(9,6,5))

# If you aren't worried about ties:  
df %>% 
  rownames_to_column('id') %>%  # creates an ID number
  gather(dept, cnt, V1:V3) %>% 
  group_by(id) %>% 
  slice(which.max(cnt)) 

# A tibble: 3 x 3
# Groups:   id [3]
  id    dept    cnt
  <chr> <chr> <dbl>
1 1     V3       9.
2 2     V1       8.
3 3     V2       5.


# If you're worried about keeping ties:
df %>% 
  rownames_to_column('id') %>%
  gather(dept, cnt, V1:V3) %>% 
  group_by(id) %>% 
  filter(cnt == max(cnt)) %>% # top_n(cnt, n = 1) also works
  arrange(id)

# A tibble: 4 x 3
# Groups:   id [3]
  id    dept    cnt
  <chr> <chr> <dbl>
1 1     V3       9.
2 2     V1       8.
3 3     V2       5.
4 3     V3       5.


# If you're worried about ties, but only want a certain department, you could use rank() and choose 'first' or 'last'
df %>% 
  rownames_to_column('id') %>%
  gather(dept, cnt, V1:V3) %>% 
  group_by(id) %>% 
  mutate(dept_rank  = rank(-cnt, ties.method = "first")) %>% # or 'last'
  filter(dept_rank == 1) %>% 
  select(-dept_rank) 

# A tibble: 3 x 3
# Groups:   id [3]
  id    dept    cnt
  <chr> <chr> <dbl>
1 2     V1       8.
2 3     V2       5.
3 1     V3       9.

# if you wanted to keep the original wide data frame
df %>% 
  rownames_to_column('id') %>%
  left_join(
    df %>% 
      rownames_to_column('id') %>%
      gather(max_dept, max_cnt, V1:V3) %>% 
      group_by(id) %>% 
      slice(which.max(max_cnt)), 
    by = 'id'
  )

# A tibble: 3 x 6
  id       V1    V2    V3 max_dept max_cnt
  <chr> <dbl> <dbl> <dbl> <chr>      <dbl>
1 1        2.    7.    9. V3            9.
2 2        8.    3.    6. V1            8.
3 3        1.    5.    5. V2            5.
> df<-data.frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(9,6,4))
> df
  V1 V2 V3
1  2  7  9
2  8  3  6
3  1  5  4
> df2<-data.frame()
> for (i in 1:nrow(df)){
+   df2[i,1]<-colnames(df[which.max(df[i,])])
+ }
> df2
  V1
1 V3
2 V1
3 V2
DF = data.frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(9,6,4))
DF %>% 
  rownames_to_column() %>%
  gather(column, value, -rowname) %>%
  group_by(rowname) %>% 
  filter(rank(-value) == 1) 
# A tibble: 3 x 3
# Groups:   rowname [3]
  rowname column value
  <chr>   <chr>  <dbl>
1 2       V1         8
2 3       V2         5
3 1       V3         9
DF %>% 
  rownames_to_column() %>%
  gather(column, value, -rowname) %>%
  group_by(rowname) %>% 
  mutate(rk = rank(-value)) %>%
  filter(rk <= 2) %>% 
  arrange(rowname, rk) 
# A tibble: 6 x 4
# Groups:   rowname [3]
  rowname column value    rk
  <chr>   <chr>  <dbl> <dbl>
1 1       V3         9     1
2 1       V2         7     2
3 2       V1         8     1
4 2       V3         6     2
5 3       V2         5     1
6 3       V3         4     2
j1 <- max.col(yourDF[, .(V1, V2, V3, V4)], "first")
yourDF$newCol <- c("V1", "V2", "V3", "V4")[j1]
DF %>%
 rowwise() %>%
 mutate(row_max = names(.)[which.max(c_across(everything()))])

     V1    V2    V3 row_max
  <dbl> <dbl> <dbl> <chr>  
1     2     7     9 V3     
2     8     3     6 V1     
3     1     5     4 V2     
DF %>%
    mutate(row_max = pmap(across(everything()), ~ names(c(...)[which.max(c(...))])))
DF <- structure(list(V1 = c(2, 8, 1), V2 = c(7, 3, 5), V3 = c(9, 6, 
4)), class = "data.frame", row.names = c(NA, -3L))
with(DF, {
  names(DF)[(V1 > V2 & V1 > V3) * 1 + (V2 > V3 & V2 > V1) * 2 + (V3 > V1 & V3 > V2)*3]
})