在 R 中,您如何根据某些标准将数据分为不同的类别?

问题描述

例如,我想根据 R2 对 R1 进行分类。 R1就像

# A tibble: 5 x 2
    lon   lat
  <dbl> <dbl>
1     1     2
2     3     5
3     6     8
4     5    10
5     3     2

和R2很像

# A tibble: 3 x 3
    lon   lat place
  <dbl> <dbl> <chr>
1     1     2 A    
2     3     6 B    
3     5     8 C 

R2 就像一个标准。我想在R1中找到我观察的相应位置。假设 R1 中的第 1 名评分如下:

  1. A 的分数:(1-1)^2 + (2-2)^2 = 0
  2. B 的分数:(1-3)^2 + (2-6)^2 = 20
  3. C 的分数:(1-5)^2 + (2-8)^2 = 52 如果任何地方的分数可能小于 3,我们将这个地方归入一个类。 最后的结果应该是这样的
# A tibble: 5 x 2
    lon   lat   place
  <dbl> <dbl>   <chr>
1     1     2   A
2     3     5   B
3     6     8   C
4     5    10   NA
5     3     2   NA

解决方法

使用一些 purrr 映射可能有一种更简洁的方法来做到这一点,但使用几个循环来代替可以获得所需的结果:

library(tidyverse)

## Create R1 and R2 as tibbles,with place as a row name
R1 <- tribble(~lon,~lat,1,2,3,5,6,8,10,2)


R2 <- tribble(~lon,~place,"A","B","C") %>% column_to_rownames(var = "place")


## Create a results tibble
results <- R1 %>% mutate(A = NaN,B = NaN,C = NaN,match = "NA")

## Function to calculate place scores
place_scores <- function(vec){
apply(R2,function(x) x-vec) %>% 
apply(.,function(x) x^2) %>% 
colSums() 
}

## Run function in a loop for each row in R1
for(i in 1:nrow(R1)){
  res <- place_scores(as.numeric(R1[i,]))
  results[i,3:5] <- res
}

## Run another loop to match the column with the lowest score and < 3
for(i in 1:nrow(results)){
  match <- ifelse(any( results[i,3:5] < 3),colnames(results[,3:5])[which.min(as.numeric(results[i,3:5]))],NA)
  results$match[i] <- match
}
results

# A tibble: 5 x 6
    lon   lat     A     B     C match
  <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1     1     2     0    20    52 A    
2     3     5    13     1    13 B    
3     6     8    61    13     1 C    
4     5    10    80    20     4 NA   
5     3     2     4    16    40 NA  
,

我还想出了一种使用 for-loop 来做到这一点的方法:

class = R2$place
for (i in 1:length(R1$place)) 
{
dist = rep(0,length(R2$place))
for (j in 1:length(R2$place)) 
   {
      dist[j] = (R1[i,1] - R2[j,1])^2 + (R1[i,2] - R2[j,2])^2
   }
R1$class[i] = class[which(dist <= 3)]
}