使用 mutate_at 在每列之后插入相对值(相对于 tibble 的第二列)
Using mutate_at to insert relative values after each column (relative to the second column of the tibble)
我有一个包含多列的数据框 (tibble),对于前两列之后的每一列,我想保留绝对值,但也插入相对于第二列的值。
例如,我从以下数据框开始(列名可能不同!):
df = tibble(val1 = 5:10, val2 = 10:15, val3 = 15:20); df
# A tibble: 6 x 3
val1 val2 val3
<int> <int> <int>
1 5 10 15
2 6 11 16
3 7 12 17
4 8 13 18
5 9 14 19
6 10 15 20
现在,对于 val2
和 val3
列,我还想在 val2
之后和 val3
之后插入一列,显示相对于 val1
。我该怎么做???
生成的小标题应如下所示:
dfrel = tibble(val1 = 5:10, val2 = 10:15, rel2 = val2/val1, val3 = 15:20, rel3 = val3/val1)
dfrel
# A tibble: 6 x 5
val1 val2 rel2 val3 rel3
<int> <int> <dbl> <int> <dbl>
1 5 10 2.00 15 3.00
2 6 11 1.83 16 2.67
3 7 12 1.71 17 2.43
4 8 13 1.62 18 2.25
5 9 14 1.56 19 2.11
6 10 15 1.50 20 2.00
不幸的是,我无法编写正确的 mutate_at 调用来在每个值列之后插入该相关列。事实上,我无法使用 funs() 编写 mutate_at 来通过访问其他列(按位置而不是名称)来修改列。
用相对值替换 val2 和 val3 可行(使用 lambda 函数而不是 funs),但不会按要求保留原始 val2 和 val3 列:
df %>%
mutate_at(vars(-1), function(v) v/.[[1]])
# A tibble: 6 x 3
val1 val2 val3
<int> <dbl> <dbl>
1 5 2.00 3.00
2 6 1.83 2.67
3 7 1.71 2.43
4 8 1.62 2.25
5 9 1.56 2.11
6 10 1.50 2.00
我所有使用 funs()
的尝试都失败了:
df %>%
mutate_at(vars(-1), funs(./.tbl[[1]]))
Error in mutate_impl(.data, dots) :
Evaluation error: object '.tbl' not found.
df %>%
mutate_at(vars(-1), funs(function(v) v/.[[1]]))
Error in mutate_impl(.data, dots) :
Column `val2` is of unsupported type function
与 相比,一个复杂的问题是我的 val1 列没有固定名称(即它并不总是被称为 val1
),所以我不能在 funs 参数中按名称使用它.另一个复杂的问题是 tibble 是动态创建的(使用大量管道运算符)并且通常不存储在变量中,所以我不能简单地除以 df[[1]]...
那么,在每列之后插入相关列(即第一列的百分比)的正确 dplyr 方法是什么?
通过将函数包装在列表中为其命名,这样 mutate_at
将创建新列。类似于以下内容(列名称可能不太理想,因此您可能需要根据需要重命名它们):
df %>% mutate_at(vars(-1), list(rel = function(v) v / .[[1]]))
# A tibble: 6 x 5
# val1 val2 val3 val2_rel val3_rel
# <int> <int> <int> <dbl> <dbl>
#1 5 10 15 2.00 3.00
#2 6 11 16 1.83 2.67
#3 7 12 17 1.71 2.43
#4 8 13 18 1.62 2.25
#5 9 14 19 1.56 2.11
#6 10 15 20 1.50 2.00
在 Psidom 的帮助下,这是我对问题的最终解决方案:
interleaveColumns = function(v) {
c(1, unlist(split(2:length(v), 1:((length(v)-1)/2)), use.names = FALSE))
}
df = tibble(val1 = 5:10, val2 = 10:15, val3 = 15:20, val4 = 25:30, val5 = 1:6);
# mutate_at can be given a named list to create a new column
# for each existing columnt (appended to the end => we need
# to reorder the columns and interleave the new columns with
# the old columns using the interleaveColumns function)
df %>%
mutate_at(vars(-1), list(rel = function(v) v/.[[1]])) %>%
select(interleaveColumns(.))
# A tibble: 6 x 9
val1 val2 val2_rel val3 val3_rel val4 val4_rel val5 val5_rel
<int> <int> <dbl> <int> <dbl> <int> <dbl> <int> <dbl>
1 5 10 2.00 15 3.00 25 5.00 1 0.200
2 6 11 1.83 16 2.67 26 4.33 2 0.333
3 7 12 1.71 17 2.43 27 3.86 3 0.429
4 8 13 1.62 18 2.25 28 3.50 4 0.500
5 9 14 1.56 19 2.11 29 3.22 5 0.556
6 10 15 1.50 20 2.00 30 3.00 6 0.600
我有一个包含多列的数据框 (tibble),对于前两列之后的每一列,我想保留绝对值,但也插入相对于第二列的值。 例如,我从以下数据框开始(列名可能不同!):
df = tibble(val1 = 5:10, val2 = 10:15, val3 = 15:20); df
# A tibble: 6 x 3
val1 val2 val3
<int> <int> <int>
1 5 10 15
2 6 11 16
3 7 12 17
4 8 13 18
5 9 14 19
6 10 15 20
现在,对于 val2
和 val3
列,我还想在 val2
之后和 val3
之后插入一列,显示相对于 val1
。我该怎么做???
生成的小标题应如下所示:
dfrel = tibble(val1 = 5:10, val2 = 10:15, rel2 = val2/val1, val3 = 15:20, rel3 = val3/val1)
dfrel
# A tibble: 6 x 5
val1 val2 rel2 val3 rel3
<int> <int> <dbl> <int> <dbl>
1 5 10 2.00 15 3.00
2 6 11 1.83 16 2.67
3 7 12 1.71 17 2.43
4 8 13 1.62 18 2.25
5 9 14 1.56 19 2.11
6 10 15 1.50 20 2.00
不幸的是,我无法编写正确的 mutate_at 调用来在每个值列之后插入该相关列。事实上,我无法使用 funs() 编写 mutate_at 来通过访问其他列(按位置而不是名称)来修改列。
用相对值替换 val2 和 val3 可行(使用 lambda 函数而不是 funs),但不会按要求保留原始 val2 和 val3 列:
df %>%
mutate_at(vars(-1), function(v) v/.[[1]])
# A tibble: 6 x 3
val1 val2 val3
<int> <dbl> <dbl>
1 5 2.00 3.00
2 6 1.83 2.67
3 7 1.71 2.43
4 8 1.62 2.25
5 9 1.56 2.11
6 10 1.50 2.00
我所有使用 funs()
的尝试都失败了:
df %>%
mutate_at(vars(-1), funs(./.tbl[[1]]))
Error in mutate_impl(.data, dots) :
Evaluation error: object '.tbl' not found.
df %>%
mutate_at(vars(-1), funs(function(v) v/.[[1]]))
Error in mutate_impl(.data, dots) :
Column `val2` is of unsupported type function
与 val1
),所以我不能在 funs 参数中按名称使用它.另一个复杂的问题是 tibble 是动态创建的(使用大量管道运算符)并且通常不存储在变量中,所以我不能简单地除以 df[[1]]...
那么,在每列之后插入相关列(即第一列的百分比)的正确 dplyr 方法是什么?
通过将函数包装在列表中为其命名,这样 mutate_at
将创建新列。类似于以下内容(列名称可能不太理想,因此您可能需要根据需要重命名它们):
df %>% mutate_at(vars(-1), list(rel = function(v) v / .[[1]]))
# A tibble: 6 x 5
# val1 val2 val3 val2_rel val3_rel
# <int> <int> <int> <dbl> <dbl>
#1 5 10 15 2.00 3.00
#2 6 11 16 1.83 2.67
#3 7 12 17 1.71 2.43
#4 8 13 18 1.62 2.25
#5 9 14 19 1.56 2.11
#6 10 15 20 1.50 2.00
在 Psidom 的帮助下,这是我对问题的最终解决方案:
interleaveColumns = function(v) {
c(1, unlist(split(2:length(v), 1:((length(v)-1)/2)), use.names = FALSE))
}
df = tibble(val1 = 5:10, val2 = 10:15, val3 = 15:20, val4 = 25:30, val5 = 1:6);
# mutate_at can be given a named list to create a new column
# for each existing columnt (appended to the end => we need
# to reorder the columns and interleave the new columns with
# the old columns using the interleaveColumns function)
df %>%
mutate_at(vars(-1), list(rel = function(v) v/.[[1]])) %>%
select(interleaveColumns(.))
# A tibble: 6 x 9
val1 val2 val2_rel val3 val3_rel val4 val4_rel val5 val5_rel
<int> <int> <dbl> <int> <dbl> <int> <dbl> <int> <dbl>
1 5 10 2.00 15 3.00 25 5.00 1 0.200
2 6 11 1.83 16 2.67 26 4.33 2 0.333
3 7 12 1.71 17 2.43 27 3.86 3 0.429
4 8 13 1.62 18 2.25 28 3.50 4 0.500
5 9 14 1.56 19 2.11 29 3.22 5 0.556
6 10 15 1.50 20 2.00 30 3.00 6 0.600