Rで互いに最も近い2つの3つの値から選択する方法は?


8

ID最も近い2つの値をそれぞれ選択しますCq。私はそれを理解したと思ったが、それは行の位置に依存する...

これが私のデータセットの形式の例です:

df <- data.frame(ID = c("A","A","A","B","B","B","C","C","C"), 
                 Cq = c(34.32,34.40,34.31,31.49,31.40,31.49,31.22,31.31,31.08))
  ID    Cq
1  A 34.32
2  A 34.40
3  A 34.31
4  B 31.49
5  B 31.40
6  B 31.49
7  C 31.22
8  C 31.31
9  C 31.08

そして私が試したもの

df4 <-df %>% 
  group_by(ID) %>% 
  arrange(Cq) %>% 
  mutate(diffvals= Cq - lag(Cq)) %>%
  filter(row_number() == 1 | row_number() == 2)

#Output
ID       Cq   diffvals
1 A      34.31   NA     
2 A      34.32   0.0100
3 B      31.40   NA     
4 B      31.49   0.0900
5 C      31.08   NA     
6 C      31.22   0.14 

そして予想される出力

 ID    Cq
1  A 34.32
2  A 34.31
3  B 31.49
4  B 31.49
5  C 31.22
6  C 31.31

以前にデータセットを並べ替えたことがありますが、何も変わりません。私も使用してみましたfilter(diffvals=wich.min==diffvals)が、2つの最小値を抽出する方法がわかりません。

あなたが何かアイデアがあれば、それは私をたくさん助けてくれるでしょう!

前もって感謝します

回答:


4

これはベースRコードで、distグループ内のすべてのペアの距離を列挙するために使用されます。つまり、

dfout <- do.call(rbind,
                 lapply(split(df,df$ID), 
                        function(v) {
                          d <- `diag<-`(as.matrix(dist(v$Cq)),NA)
                          d[lower.tri(d)] <- NA
                          v[which(d==min(d,na.rm = T),arr.ind = T),]
                        }
                 ))

そのような

> dfout
    ID    Cq
A.1  A 34.32
A.3  A 34.31
B.4  B 31.49
B.6  B 31.49
C.7  C 31.22
C.8  C 31.31

3

dplyr1つのオプションを使用するには、full_joinitself基づいてwith を実行しIDます。それ自体と組み合わせて生成された行を削除し、それぞれのID違いが最小の行を選択して、長い形式のデータを取得します。

library(dplyr)

df %>%
  mutate(Row = row_number()) %>%
  full_join(df, by = 'ID') %>%
  group_by(ID, Row) %>%
  filter(Cq.x != Cq.y) %>%
  group_by(ID) %>%
  slice(which.min(abs(Cq.x - Cq.y))) %>%
  tidyr::pivot_longer(cols  = starts_with('Cq')) %>%
  select(-Row, -name)

#  ID    value
#  <fct> <dbl>
#1 A      34.3
#2 A      34.3
#3 B      31.5
#4 B      31.4
#5 C      31.2
#6 C      31.3

1

これを試して:

library(tidyverse)
df <- data.frame(ID = c("A","A","A","B","B","B","C","C","C"), 
                 Cq = c(34.32,34.40,34.31,31.49,31.40,31.49,31.22,31.31,31.08))

df_summ <- 
  df %>% 
  group_by(ID) %>% 
  arrange(Cq) %>% 
  mutate(
    prev = lag(Cq),
    diff= Cq - lag(Cq)) %>% 
  drop_na()
df_summ %>% 
  group_by(ID) %>% 
  summarise(diff = min(diff)) %>% 
  left_join(df_summ) %>% 
  select(-diff) %>% 
  pivot_longer(c(Cq, prev), values_to = "cq") %>% 
  select(-name)

よろしく


1

ベースR

do.call(rbind, lapply(split(df, df$ID), function(x){ 
  cell <- order(abs(outer(x$Cq, x$Cq, `-`)))[-seq(nrow(x))][1] - 1;
  x[c((cell %/% nrow(x)) + 1, (cell %% nrow(x)) + 1),]}))
#>     ID    Cq
#> A.1  A 34.32
#> A.3  A 34.31
#> B.4  B 31.49
#> B.6  B 31.49
#> C.7  C 31.22
#> C.8  C 31.31

0

出力は異なるが機能的に同等

do.call(rbind,
  by(df,list(df$ID),function(x){
    tmp=abs(outer(x$Cq,x$Cq,"-"))
    tmp[upper.tri(tmp,diag=T)]=Inf
    x$Cq[which(tmp==min(tmp),arr.ind=T)]
  })
)

   [,1]  [,2]
A 34.31 34.32
B 31.49 31.49
C 31.31 31.22
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.