R语言 生信R for data science

dplyr 1.0.0 之 rowwise

2020-06-06  本文已影响0人  热衷组培的二货潜

dplyr 1.0.0 之 rowwise

加载包

library(tidyverse, warn.conflicts = F)

<br />在 R 中 dplyr 通常是对列进行操作,然而对于行处理方面还是b比较困难,本节我们将学习通过 rowwise()函数来对数据进行行处理,常与 c_across() 连用。<br />
<br />本节中列举了三个常见的案例:<br />

<br />当然这些问题我们可以通过类似 for 等循环来进行操作,但是我们可以通过管道的形式进行更便捷的操作,这里作者有一句经典的话:<br />

Of course, someone has to write loops. It doesn’t have to be you. — Jenny Bryan

<a name="a6d31b10"></a>

实战:

<br />rowwise 按行来进行分组,和 group_by() 函数一样,并不会改变数据得内容,仅仅是进行分组:<br />

df <- tibble(x = 1:2, y = 3:4, z = 5:6)
df %>% rowwise()

# 计算的是数据中所有的数值的平均值
df %>% mutate(m = mean(c(x, y, z)))

# 计算每一列的平均值
df %>% mutate(across(everything(), ~mean(.x, na.rm = T)))

# 计算的是每一行的平均值
df %>% rowwise() %>% mutate(m = mean(c(x, y, z)))

<a name="c5649d16"></a>

rowwise() 与 summarise() 函数连用

df <- tibble(name = c("Mara", "Hadley"), x = 1:2, y = 3:4, z = 5:6)

# 结果仅仅只有值
df %>% 
  rowwise() %>% 
  summarise(m = mean(c(x, y, z)))

# 可以通过加上需要处理的行作为 summarise() 的行名,可以使用 `rowwise(name)`,保留 `name` 列
df %>% 
  rowwise(name) %>% 
  summarise(m = mean(c(x, y, z)))

<a name="e2c5cace"></a>

每一行进行统计

df <- tibble(id = 1:6, w = 10:15, x = 20:25, y = 30:35, z = 40:45)
df

# 使用 `rowwise` 对数据进行行分组 
rf <- df %>% rowwise(id)

rf %>% mutate(total = sum(c(w, x, y, z)))
rf %>% summarise(total = sum(c(w, x, y, z)))

<a name="b2d1310f"></a>

多列 c_across() 联合操作

rf %>% mutate(total = sum(c_across(w:z)))


rf %>% mutate(total = sum(c_across(where(is.numeric))))

<a name="c275761c"></a>

rowwise()c_across()across() 连用

ungroup() 取消分组,这里表示取消按照行进行分组

rf %>% 
  mutate(total = sum(c_across(w:z))) %>% 
  ungroup() %>% 
  mutate(across(w:z, ~ . / total))

<a name="b09a9c97"></a>

行处理函数总结:rowSums()rowMeans()

内置行处理函数更快,对行进行操作,没有分成行、然后统计,最后连接到一起。

df %>% mutate(total = rowSums(across(where(is.numeric))))

df %>% mutate(mean = rowMeans(across(where(is.numeric))))

<a name="ec71b358"></a>

列表-列

df <- tibble(
  x = list(1, 2:3, 4:6)
)

# 计算列表中向量的个数,返回的是列的长度,而不是列表中每一个向量的长度
df %>% mutate(l = length(x))

# 计算列表中单个向量的长度
df %>% mutate(l = lengths(x))

# 或者利用 sapply()、vapply() map() 函数功能实现
df %>% mutate(l = sapply(x, length))

df %>% mutate(l = purrr::map_int(x, length))

# 我们可以通过 rowwise() 函数来实现
df %>% 
  rowwise() %>% 
  mutate(l = length(x))

<a name="5d04e51c"></a>

Subsetting:取子集

df <- tibble(g = 1:2, y = list(1:3, "a"))
gf <- df %>% group_by(g)
rf <- df %>% rowwise(g)

gf %>% mutate(type = typeof(y), length = length(y))

rf %>% mutate(type = typeof(y), length = length(y))

<a name="2c6a15d0"></a>

通过 for 循环来计算列表中子向量的长度应该取 [[]] 而非 []

# grouped
out1 <- integer(2)
for (i in 1:2) {
  out1[[i]] <- length(df$y[i])
}
out1

# rowwise
out2 <- integer(2)
for (i in 1:2) {
  out2[[i]] <- length(df$y[[i]])
}
out2

<a name="709da5d0"></a>

group_by()rowwise() 分组后添加新的列时,应该注意以下

gf %>% mutate(y2 = y)

# 报错,由于 rowwise 的结果是列表中子向量的值,长度不一致

# rf %>% mutate(y2 = y)

# 通过 `list()` 函数将其存储为一个 list()

rf %>% mutate(y2 = list(y))

<a name="9c427e2d"></a>

Modelling:建模(无脑运行的。)

nest_by() 分组存储为一个 list

by_cyl <- mtcars %>% nest_by(cyl)
by_cyl

<a name="2524ce58"></a>

按行线性建模

mods <- by_cyl %>% mutate(mod = list(lm(mpg ~ wt, data = data)))
mods

mods <- mods %>% mutate(pred = list(predict(mod, data)))
mods

<a name="5105b123"></a>

summarise() 函数进行统计

mods %>% summarise(rmse = sqrt(mean((pred - data$mpg) ^ 2)))

mods %>% summarise(rsq = summary(mod)$r.squared)

mods %>% summarise(broom::glance(mod))


mods %>% summarise(broom::tidy(mod))

<a name="35610ed3"></a>

重复的函数调用:按行传入变量参数

<br />rowwise() 不仅适用于返回长度为 1 的向量的函数; 如果结果是一个列表,它可以与任何函数一起连用。这意味着 rowwise()mutate() 提供了一种优雅的方法,可以多次使用不同的参数调用函数,将输出存储在输入旁边。<br />

一定要用 list() 函数来将命令括起来,比如 list(runif(n, min, max)) 而非 runif(n, min, max)

df <- tribble(
  ~ n, ~ min, ~ max,
    1,     0,     1,
    2,    10,   100,
    3,   100,  1000,
)

df %>% 
  rowwise() %>% 
  mutate(data = list(runif(n, min, max)))
# 会报错
df %>% 
  rowwise() %>% 
  mutate(data = runif(n, min, max))

<a name="194c5bcf"></a>

两两多重组合:tidyr::expand_grid() 函数

# 这里就会得到  3*3 九种结果
df <- expand.grid(mean = c(-1, 0, 1), sd = c(1, 10, 100))

df %>% 
  rowwise() %>% 
  mutate(data = list(rnorm(10, mean, sd)))

<a name="bc13740f"></a>

各种功能:结合 do.call()

df <- tribble(
   ~rng,     ~params,
   "runif",  list(n = 10), 
   "rnorm",  list(n = 20),
   "rpois",  list(n = 10, lambda = 5),
) %>%
  rowwise()

df %>% 
  mutate(data = list(do.call(rng, params)))

<a name="772ab8dd"></a>

以前的操作

作者建议使用 purrrmap() 函数执行行操作,但是又会增加额外学习。

上一篇下一篇

猜你喜欢

热点阅读