web-dev-qa-db-ja.com

Rの特定の列に最も近い値

以下の列x3に最も近い値を見つけたいのですが。

data=data.frame(x1=c(24,12,76),x2=c(15,30,20),x3=c(45,27,15))
data
  x1 x2 x3
1 24 15 45
2 12 30 27
3 76 20 15

したがって、望ましい出力は

Closest_Value_to_x3
   24
   30
   20

助けてください。ありがとうございました

14
melik

max.col(-abs(data[, 3] - data[, -3]))を使用して最も近い値の列位置を見つけ、この結果を行列の一部として使用して、データから目的の値を抽出します。行列はcbindによって返されます

col <- 3
data[, -col][cbind(1:nrow(data),
                   max.col(-abs(data[, col] - data[, -col])))]
#[1] 24 30 20
13
markus

tidyverseソリューション:

data %>%
  rowid_to_column() %>%
  gather(var, val, -c(x3, rowid)) %>%
  mutate(temp = x3 - val) %>%
  group_by(rowid) %>%
  filter(abs(temp) == min(abs(temp))) %>%
  ungroup() %>%
  select(val)

    val
  <dbl>
1    24
2    30
3    20

まず、行IDを追加します。次に、データをワイドからロングに変換します。 3番目に、「x3」と他の変数との差を計算します。最後に、行IDでグループ化し、絶対差が最も小さい行を保持します。

または:

data %>%
  rowid_to_column() %>%
  gather(var, val, -c(x3, rowid)) %>%
  mutate(temp = x3 - val) %>%
  group_by(rowid) %>%
  filter(abs(temp) == min(abs(temp))) %>%
  ungroup() %>%
  pull(val)

[1] 24 30 20

または、@ markusが最初に提案したアプローチを使用します(列の名前が「x」であると想定しています)。

data %>%
 mutate(temp = paste0("x", max.col(-abs(.[, -3] - .[, 3])))) %>%
 rowwise() %>%
 summarise(val = eval(as.symbol(temp)))

    val
  <dbl>
1   24.
2   30.
3   20.

まず、 "x3"に関する絶対差が最も小さい変数の列インデックスを評価し、 "x"と組み合わせます。次に、xと列インデックスの組み合わせを変数として評価し、適切な値を返します。

また、@ markusからアイデアを借用しています(列の名前が「x」であるとは想定していません)。

data %>%
 mutate(temp = max.col(-abs(.[, -3] - .[, 3]))) %>%
 rowwise %>%
 mutate(temp = names(.)[[temp]]) %>%
 summarise(val = eval(as.symbol(temp)))

まず、 "x3"に関する絶対差が最も小さい変数の列インデックスを評価します。次に、列インデックスに基づいて列名を返します。最後に、それを変数として評価し、適切な値を返します。

または、列インデックスではなく名前で「x3」変数を参照できるバリアント(@markusからの基本的な考え方):

data %>%
 mutate(temp = max.col(-abs(.[, !grepl("x3", colnames(.))] - .[, grepl("x3", colnames(.))]))) %>% 
 rowwise %>%
 mutate(temp = names(.)[[temp]]) %>%
 summarise(val = eval(as.symbol(temp)))
3
tmfmnk

これはmatrixStatsを使用した別のアプローチです

x <- as.matrix(data[,-3L])
y <- abs(x - .subset2(data, 3L))
x[matrixStats::rowMins(y) == y]
# [1] 24 30 20

またはbasevapplyを使用して

x <- as.matrix(data[,-3L])
y <- abs(x - .subset2(data, 3L))
vapply(1:nrow(data), 
       function(k) x[k,][which.min(y[k,])], 
       numeric(1))
# [1] 24 30 20
3
niko

関数を定義するclosest_to_3はベクターを操作し、3番目のメンバーに最も近いベクターの値を返します。

closest_to_3 <- function(v) v[-3][which.min(abs( v[-3]-v[3] ))]

(イディオムv[-3]は、3番目のメンバーをvから削除します。)次に、この関数をデータフレームの各行に適用します。

apply(data, 1, closest_to_3)
#[1] 24 30 20
2
grand_chat