如何匹配 2 标准内的最小差异和 return R 中的索引

How to match the min difference within the 2 criterion and return the index in R

这是我的df。

index   firmcode    year    indcode     ROA
  0      a         2006      03         0.1
  1      b         2006      03         0.2
  2      c         2006      03         0.4
  3      d         2006      03         0.7   
  4      e         2006      07         0.3
  5      f         2006      07         0.8
  6      g         2006      07         1.1
  7      h         2006      07         2.1

我希望它是这样的。这是匹配最近公司的ROA(同年同indcode,同公司除外)

index   firmcode    year    indcode     ROA   diff_min_firmcode
  0      a         2006      03         0.1         b  
  1      b         2006      03         0.2         a
  2      c         2006      03         0.4         b          
  3      d         2006      03         0.7         c
  4      e         2006      07         0.3         f 
  5      f         2006      07         0.8         g 
  6      g         2006      07         1.1         f
  7      h         2006      07         2.1         g 

如何获取 df['diff_min_firmcode'] 列?

平局会怎样?

你可以试试这个答案 -

fun <- function(a, b) {
  apply(abs(outer(a, a, `-`)), 1, function(x) b[x == min(x[x != 0])[1]])  
}

如果您有多个年份并且只想在每个特定年份内进行匹配,您可以这样做 -

library(dplyr)

df %>%
  group_by(year, indcode) %>%
  mutate(diff_min_firmcode = fun(ROA, firmcode)) %>%
  ungroup

#  index firmcode  year indcode   ROA diff_min_firmcode
#  <int> <chr>    <int>   <int> <dbl> <chr>            
#1     0 a         2006       3   0.1 b                
#2     1 b         2006       3   0.2 a                
#3     2 c         2006       3   0.4 b                
#4     3 d         2006       3   0.7 c                
#5     4 e         2006       7   0.3 f                
#6     5 f         2006       7   0.8 g                
#7     6 g         2006       7   1.1 f                
#8     7 h         2006       7   2.1 g                           

这是另一种方法,使用 full_join 和相同的 data.frame。在 filter 排除行以避免与自己的 ROA 匹配后,您可以确定 ROA 与同一 yearindcode 组中的其他人之间的最小差异。

library(dplyr)

full_join(df, df, by = c("year", "indcode")) %>%
  filter(index.x != index.y) %>%
  group_by(firmcode.x, year, indcode) %>%
  mutate(diff_min_firmcode = firmcode.y[which.min(abs(ROA.x - ROA.y))]) %>%
  distinct(firmcode.x, .keep_all = TRUE)

输出

  index.x firmcode.x  year indcode ROA.x index.y firmcode.y ROA.y diff_min_firmcode
    <int> <chr>      <int>   <int> <dbl>   <int> <chr>      <dbl> <chr>            
1       0 a           2006       3   0.1       1 b            0.2 b                
2       1 b           2006       3   0.2       0 a            0.1 a                
3       2 c           2006       3   0.4       0 a            0.1 b                
4       3 d           2006       3   0.7       0 a            0.1 c                
5       4 e           2006       7   0.3       5 f            0.8 f                
6       5 f           2006       7   0.8       4 e            0.3 g                
7       6 g           2006       7   1.1       4 e            0.3 f                
8       7 h           2006       7   2.1       4 e            0.3 g

这是您可以用于此问题的另一种方法:

library(dplyr)
library(tidyr)
library(purrr)

df %>%
  group_by(year, indcode) %>%
  mutate(output = map(ROA, ~ abs(ROA - .x))) %>%
  unnest_wider(col = output) %>%
  rowwise() %>%
  mutate(inds = which(c_across(contains("...")) == 
                        min(c_across(contains("..."))[c_across(contains("...")) != 0])[1])) %>%
  select(!contains("...")) %>%
  group_by(year, indcode) %>%
  mutate(diff_min = map_chr(inds, ~ firmcode[.x]))

# A tibble: 8 x 7
# Groups:   year, indcode [2]
  index firmcode  year indcode   ROA  inds diff_min
  <int> <chr>    <int>   <int> <dbl> <int> <chr>   
1     0 a         2006       3   0.1     2 b       
2     1 b         2006       3   0.2     1 a       
3     2 c         2006       3   0.4     2 b       
4     3 d         2006       3   0.7     3 c       
5     4 e         2006       7   0.3     2 f       
6     5 f         2006       7   0.8     3 g       
7     6 g         2006       7   1.1     2 f       
8     7 h         2006       7   2.1     3 g