使用 dplyr/tidyverse 进行类似扫描的操作

Jam*_*ran 5 r dplyr tidyverse

例如,我感兴趣的是用从每行中减去行最小值的列替换(几乎)所有data.frame列tibble。例如,如果X是一个数值矩阵,那么在基本 RI 中会写:

X = sweep(X, 1, apply(X, 1, min))
Run Code Online (Sandbox Code Playgroud)

我当前使用我拥有的数据执行此操作的函数(我将立即解释格式)将数字列拉出到矩阵中,进行扫描,然后cbind将转换后的数据和非数字数据再次组合在一起。那是:

subtractMin = function(data){
  X = data %>% 
    select(starts_with("X")) %>% 
    as.matrix()

  X = sweep(X, 1, apply(X, 1, min))

  labels = data %>% 
    select(-starts_with("X"))

  return(cbind(labels, X))
}
Run Code Online (Sandbox Code Playgroud)

我觉得这效率很低,必须有一种更聪明的方法。

我认为了解上下文并不重要,但我的数据有 77 行和 1133 列。其中四列包含标签信息,其余 1129 列包含每次观察的数值测量值(如果您关心的话,它们是光谱)。数值变量的数量如此之多,以至于单个mutate变量并不是前进的道路。同样 - 您仍然需要知道行最小值才能对每行进行标准化。

我被要求添加一些数据。原始数据有1000多列,所以我将提供一个较小的数据集

> x.df
      nm X1799.38928 X1798.01526 X1796.64124 source color rep
1 s001c1   13901.944   13889.056   13883.334     01     c   1
2 s001c2   17293.586   17279.375   17291.365     01     c   2
3 s001c3    8011.764    8028.584    8033.548     01     c   3
4 s001c4    7499.272    7510.719    7517.064     01     c   4
5 s001c5   20300.408   20293.604   20297.185     01     c   5
Run Code Online (Sandbox Code Playgroud)

Mau*_*ers 5

(就其价值而言,我认为这里的否决票有点严厉且没有根据。问题陈述很清楚,示例数据已包含在编辑中。)

您可以通过将数字列中的数据从宽转换为长(使用gather)、按行分组(使用group_by)、减去最小值(使用mutate)以及从长转换回宽(使用spread)来实现您的目标。

library(tidyverse)
df %>%
    gather(k, v, starts_with("X")) %>%
    group_by(nm) %>%
    mutate(v = v - min(v)) %>%
    spread(k, v) %>%
    select(names(df))
## A tibble: 5 x 7
## Groups:   nm [5]
#  nm     X1799.38928 X1798.01526 X1796.64124 source color   rep
#  <fct>        <dbl>       <dbl>       <dbl>  <int> <fct> <int>
#1 s001c1       18.6         5.72        0.        1 c         1
#2 s001c2       14.2         0.         12.0       1 c         2
#3 s001c3        0.         16.8        21.8       1 c         3
#4 s001c4        0.         11.4        17.8       1 c         4
#5 s001c5        6.80        0.          3.58      1 c         5
Run Code Online (Sandbox Code Playgroud)

样本数据

df <- read.table(text =
    "nm X1799.38928 X1798.01526 X1796.64124 source color rep
1 s001c1   13901.944   13889.056   13883.334     01     c   1
2 s001c2   17293.586   17279.375   17291.365     01     c   2
3 s001c3    8011.764    8028.584    8033.548     01     c   3
4 s001c4    7499.272    7510.719    7517.064     01     c   4
5 s001c5   20300.408   20293.604   20297.185     01     c   5")
Run Code Online (Sandbox Code Playgroud)