我想按列排列值。
我有以下数据框:
dput(test)
structure(list(Name = c("A", "B", "C", "D"), Margin = c(744,
3196.4722, 0, 394), T1 = c(420, 200, 2150, 70), T2 = c(630, 285,
2365, 84), T3 = c(630, 335, 2580, 105), T4 = c(666, 410, 2795,
128), T5 = c(2244, 2961.7931, 3010, 142), T6 = c(2244, 3652.472,
3440, 151), T7 = c(2244, 3722.472, 3870, 168), T8 = c(2244, 3887.472,
5160, 187), T9 = c(2244, 4112.472, 6450, 225), T10 = c(2244,
4337.472, 6450, 225), T11 = c(798, 3567.472, 4300, 112), T12 = c(630,
3582.472, 4300, 111), T13 = c(702, 3582.472, 4300, 112), T14 = c(3600,
4637.472, 3440, 78), T15 = c(744, 3067.306, 2580, 274), T16 = c(744,
2770.5666, 2580, 197), T17 = c(744, 3138.806, 2580, 80), T18 = c(2244,
3920.0836, 3870, 401), T19 = c(2244, 2789.1117, 1290, 127)), .Names = c("Name",
"Margin", "T1", "T2", "T3", "T4", "T5", "T6", "T7", "T8", "T9",
"T10", "T11", "T12", "T13", "T14", "T15", "T16", "T17", "T18",
"T19"), row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"
))
每一行都有名称中的唯一ID,我想对列进行排名,以确定哪个列与margin列中的值相等或最小。
理想的输出是:
Name Margin Closest_Column
A 744.000 T15
断裂关系可能是随机的。
我的尝试:
nm1 <- paste("rank", names(test)[3:21], sep="_")
test[nm1] <- mutate_all(test[3:21],funs(rank(., ties.method="first")))
答案 0 :(得分:3)
我会选择长格式
library(tidyr)
library(dplyr)
test %>%
gather(Variable, Value, -(Name:Margin)) %>%
group_by(Name, Margin) %>%
summarise(Closest = Variable[which.min(abs(Value - Margin))])
# A tibble: 4 x 3
# Groups: Name [?]
# Name Margin Closest
# <chr> <dbl> <chr>
# 1 A 744.000 T15
# 2 B 3196.472 T17
# 3 C 0.000 T19
# 4 D 394.000 T18
或使用data.table
library(data.table)
melt(setDT(test), 1:2
)[, .(Closest = variable[which.min(abs(value - Margin))]),
by = .(Name, Margin)]
# Name Margin Closest
# 1: A 744.000 T15
# 2: B 3196.472 T17
# 3: C 0.000 T19
# 4: D 394.000 T18
答案 1 :(得分:2)
使用cbind.data.frame将前两列与从所选名称构成的列对齐,列名绝对值为最小值减去边距:
public function getEmpSearchResult($businessunit_id,$department_id,$jobtitle)
{
$i=0;
$WHERE = "";
if (!empty($businessunit_id))
{
if($i==1) {
$WHERE = $WHERE." AND";
}
$WHERE = "businessunit_id"."=".$businessunit_id;
$i=1;
}
if (!empty($department_id))
{ if($i==1) {
$WHERE = $WHERE." AND";
}
$WHERE = $WHERE." department_id"."=".$department_id;
$i=1;
}
if (!empty($jobtitle))
{
if($i==1) {
$WHERE = $WHERE." AND";
}
$WHERE = $WHERE." jobtitle_id"."=".$jobtitle;
$i=1;
}
$query = "SELECT * FROM `main_employees_summary` WHERE $WHERE ";
$data = $db->query($query)->fetchAll();
return $data;
答案 2 :(得分:1)
如果我们需要使用tidyverse
,则一种方法是rowwise
,然后找到“边距”与其他列之间的最小差异索引以获取列名称
test %>%
rowwise() %>%
do(data.frame(.[1:2], Closest_column = names(.)[3:21][which.min(abs(.[[2]]-
unlist(.[3:21])))]))
# A tibble: 4 x 3
# Name Margin Closest_column
#* <chr> <dbl> <chr>
#1 A 744.000 T15
#2 B 3196.472 T17
#3 C 0.000 T19
#4 D 394.000 T18
或另一种选择是
library(tidyverse)
gather(test, Closest_column, val, T1:T19) %>%
group_by(Name) %>%
slice(which.min(abs(Margin - val))) %>%
select(-val)
# A tibble: 4 x 3
# Groups: Name [4]
# Name Margin Closest_column
# <chr> <dbl> <chr>
#1 A 744.000 T15
#2 B 3196.472 T17
#3 C 0.000 T19
#4 D 394.000 T18
使用base R
,有效选项为max.col
cbind(test[1:2],
Closest_column = names(test)[3:21][max.col(-abs(test[3:21]-test[[2]]), 'first')])
# Name Margin Closest_column
#1 A 744.000 T15
#2 B 3196.472 T17
#3 C 0.000 T19
#4 D 394.000 T18