如何使用dplyr`rowwise()`列号代替列名

时间:2019-04-25 18:29:06

标签: r dplyr

library(tidyverse)
df <- tibble(col1 = c(5, 2), col2 = c(6, 4), col3 = c(9, 9))
df %>% rowwise() %>% mutate(col4 = sd(c(col1, col3)))
# # A tibble: 2 x 4
#    col1  col2  col3  col4
#   <dbl> <dbl> <dbl> <dbl>
# 1     5     6     9  2.83
# 2     2     4     9  4.95

问了一系列问题之后,我终于可以计算出各行之间的标准差了。参见上面的代码。

但是我不能在生产代码中使用列名,因为我从中提取的数据库喜欢定期更改列名。对我来说幸运的是,相对列位置始终是相同的。

因此,我将仅使用列号。并且让我们检查一下以确保可以随便交换内容:

identical(df$col1, df[[1]])
# [1] TRUE

是的,我可以交换df[[1]]代替df$col1。我想我是这样做的。

df %>% rowwise() %>% mutate(col4 = sd(c(.[[1]], .[[3]])))  
# # A tibble: 2 x 4
#    col1  col2  col3  col4
#   <dbl> <dbl> <dbl> <dbl>
# 1     5     6     9  3.40
# 2     2     4     9  3.40

df %>% rowwise() %>% {mutate(col4 = sd(c(.[[1]], .[[3]])))} 
# Error in mutate_(.data, .dots = compat_as_lazy_dots(...)) : 
#   argument ".data" is missing, with no default 

不,这些看起来不起作用,因为结果与我的原始照片不同。如果您确实需要知道为什么I made a separate question,我就不能使用apply。

df %>% mutate(col4 = apply(.[, c(1, 3)], 1, sd))

如何将dplyr rowwise()应用于列号而不是名称?

3 个答案:

答案 0 :(得分:1)

进行.[[1]]后使用[[3]]或。rowwise(按行分组-每组只有一行)的问题是,它破坏了分组结构并提取了整个柱。为了避免这种情况,我们可以在进行row_number()之前创建一个rowwise列,然后根据该索引对这些列进行子集

library(dplyr)
df %>%
    mutate(rn = row_number()) %>% # create a sequence of row index
    rowwise %>% 
    mutate(col4 = sd(c(.[[1]][rn[1]], .[[3]][rn[1]]))) %>% #extract with index
    select(-rn)
#Source: local data frame [2 x 4]
#Groups: <by row>

# A tibble: 2 x 4
#   col1  col2  col3  col4
#  <dbl> <dbl> <dbl> <dbl>
#1     5     6     9  2.83
#2     2     4     9  4.95

或者另一个选择是map中的purrr,我们在row_number()上循环并对数据集的行进行子集设置

library(purrr)
df %>% 
  mutate(col4 = map_dbl(row_number(), ~ sd(c(df[[1]][.x], df[[3]][.x]))))
# A tibble: 2 x 4
#   col1  col2  col3  col4
#   <dbl> <dbl> <dbl> <dbl>
#1     5     6     9  2.83
#2     2     4     9  4.95

或者另一个选择是pmap(如果我们不想使用row_number()

df %>%
    mutate(col4 = pmap_dbl(.[c(1, 3)], ~ sd(c(...))))
# A tibble: 2 x 4
#   col1  col2  col3  col4
#  <dbl> <dbl> <dbl> <dbl>
#1     5     6     9  2.83
#2     2     4     9  4.95

当然,最简单的方法是使用rowSds中的matrixStats,如带假名的帖子here

中所述

注意:以上所有方法都不需要任何重塑

答案 1 :(得分:1)

由于您不一定知道列名,但是知道需要标准偏差的列的位置等,因此我将整形为长数据并添加一个ID列。您可以按位置而不是列名进行收集,方法是给出应成为键的列号,或从键中省略的列号。这样,您无需按列指定这些值,因为您已经将它们全部放在一列中。然后,您可以将这些摘要值重新添加到原始的宽形数据中。

library(dplyr)
library(tidyr)

df <- tibble(col1 = c(5, 2), col2 = c(6, 4), col3 = c(9, 9)) %>%
  mutate(id = row_number())

df %>%
  mutate(id = row_number()) %>%
  gather(key, value, 1, 3) %>%
  group_by(id) %>%
  summarise(sd = sd(value)) %>%
  inner_join(df, by = "id")
#> # A tibble: 2 x 5
#>      id    sd  col1  col2  col3
#>   <int> <dbl> <dbl> <dbl> <dbl>
#> 1     1  2.83     5     6     9
#> 2     2  4.95     2     4     9

根据需要按位置重新排列列。

答案 2 :(得分:1)

一种将数据转置,转换为矩阵,计算标准偏差,再次转置并转换为小标题的方法。

df %>%
  t %>%
  rbind(col4 = c(sd(.[c(1, 3),1]), sd(.[c(1, 3),2]))) %>%
  t %>%
  as_tibble()