如何使用dplyr扫描特定列?

Kon*_*lph 12 r dplyr

对我的数据类型来说,一个非常常见的操作是将归一化因子应用于所有列.这可以使用sweep或有效地完成scale:

normalized = scale(data, center = FALSE, scale = factors)
# or
normalized = sweep(data, 2, factors, `/`)
Run Code Online (Sandbox Code Playgroud)

哪里

data = structure(list(A = c(3L, 174L, 6L, 1377L, 537L, 173L),
    B = c(1L, 128L, 2L, 1019L, 424L, 139L),
    C = c(3L, 66L, 2L, 250L, 129L, 40L),
    D = c(4L, 57L, 4L, 251L, 124L, 38L)),
    .Names = c("A", "B", "C", "D"),
    class = c("tbl_df", "data.frame"), row.names = c(NA, -6L))

factors = c(A = 1, B = 1.2, C = 0.8, D = 0.75)
Run Code Online (Sandbox Code Playgroud)

但是,当我的数据在前面有其他列时,如何使用dplyr执行此操作?我可以在单独的语句中完成它,但我想在一个管道中完成它.这是我的数据:

data = structure(list(ID = c(1, 2, 3, 4, 5, 6),
    Type = c("X", "X", "X", "Y", "Y", "Y"),
    A = c(3L, 174L, 6L, 1377L, 537L, 173L),
    B = c(1L, 128L, 2L, 1019L, 424L, 139L),
    C = c(3L, 66L, 2L, 250L, 129L, 40L),
    D = c(4L, 57L, 4L, 251L, 124L, 38L)),
    .Names = c("ID", "Type", "A", "B", "C", "D"),
    class = c("tbl_df", "data.frame"), row.names = c(NA, -6L))
Run Code Online (Sandbox Code Playgroud)

而且我想改变数据列而不触及前两列.通常我可以这样做mutate_each; 但是,我怎么不能将我的规范化因子传递给该函数:

data %>% mutate_each(funs(. / factors), A:D)
Run Code Online (Sandbox Code Playgroud)

这毫不奇怪,假设我要划分的每一列通过factors,而不是由它的匹配因素每一列.

jaz*_*rro 11

鉴于akrun的鼓励,让我在这里发布我所做的答案.我只是直觉地认为您可能要求R指示具有相同名称的列来执行此操作mutate_each.例如,如果.指示列,A我认为A从另一个data.frame 命名的另一列可能是dplyr喜欢的.所以,我创建了一个数据框factors然后使用mutate_each.结果似乎是正确的.由于我没有技术背景,我担心我无法提供任何解释.我希望你不介意.

factors <- data.frame(A = 1, B = 1.2, C = 0.8, D = 0.75)

mutate_at(data, vars(A:D), funs(. / foo$.))

# By the time I answered this question, the following was working.
# But mutate_each() is now deprecated.

# mutate_each(data, funs(. / factors$.), A:D)

#  ID Type    A           B      C          D
#1  1    X    3   0.8333333   3.75   5.333333
#2  2    X  174 106.6666667  82.50  76.000000
#3  3    X    6   1.6666667   2.50   5.333333
#4  4    Y 1377 849.1666667 312.50 334.666667
#5  5    Y  537 353.3333333 161.25 165.333333
#6  6    Y  173 115.8333333  50.00  50.666667
Run Code Online (Sandbox Code Playgroud)

编辑

这也有效.鉴于数据框是列表的特例,这也许并不令人惊讶.

# Experiment
foo <- list(A = 1, B = 1.2, C = 0.8, D = 0.75)

mutate_at(data, vars(A:D), funs(. / foo$.))

# mutate_each(data, funs(. / foo$.), A:D)

#  ID Type    A           B      C          D
#1  1    X    3   0.8333333   3.75   5.333333
#2  2    X  174 106.6666667  82.50  76.000000
#3  3    X    6   1.6666667   2.50   5.333333
#4  4    Y 1377 849.1666667 312.50 334.666667
#5  5    Y  537 353.3333333 161.25 165.333333
#6  6    Y  173 115.8333333  50.00  50.666667
Run Code Online (Sandbox Code Playgroud)

  • @KonradRudolph这就是我使用`data.table`来实现这一点的方法 - `setDT(data)[,names(factors):= Map("/",.SD,factors),. SDcols = names(factors)] ` - 不确定这是否会清除你的直觉性吧. (3认同)

tmf*_*mnk 3

dplyr 1.0.0,您可以执行以下操作:

data %>%
 rowwise() %>%
 mutate(across(A:D)/factors)

     ID Type      A       B      C      D
  <dbl> <chr> <dbl>   <dbl>  <dbl>  <dbl>
1     1 X         3   0.833   3.75   5.33
2     2 X       174 107.     82.5   76   
3     3 X         6   1.67    2.5    5.33
4     4 Y      1377 849.    312.   335.  
5     5 Y       537 353.    161.   165.  
6     6 Y       173 116.     50     50.7 
Run Code Online (Sandbox Code Playgroud)