R 使用mutate_at在每列之后插入相对值(相对于TIBLE的第二列)

R 使用mutate_at在每列之后插入相对值(相对于TIBLE的第二列),r,dplyr,mutate,tibble,R,Dplyr,Mutate,Tibble,我有一个包含多个列的dataframe 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

我有一个包含多个列的dataframe 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
不幸的是,我无法在调用时编写适当的mutate_,以便在每个值列之后插入该相对列。事实上,我无法使用funs编写一个mutate_,它通过按位置而不是名称访问其他列来修改列

用相对值替换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
与之相比的一个复杂之处是,我的val1列没有固定的名称,即它并不总是被称为val1,因此我不能在funs参数中按名称使用它。另一个复杂的问题是,tibble是使用大量管道操作符动态创建的,通常不存储在变量中,因此我不能简单地用df[[1]]除以


那么,dplyr插入相对列(即每列后面第一列的百分比)的正确方法是什么呢?

通过将函数包装到列表中来为其命名,这样mutate\u将创建新的列。以下列名称可能不太理想,因此如果需要,您可能需要重命名它们:


在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

谢谢,在列表中加后缀是我从来没有想到过的。命名不是问题,因为无论如何我都会在kable中对col.names进行后期处理。不幸的是,您的解决方案将所有相关列追加到末尾。有没有办法在每个值列后面插入新列?列的数量不是固定的,因为它们是来自不同死亡率表的值,我需要为一个发布报告这些值,所以手动重新排列并不简单。如何对列名进行排序?链%>%selectsortnames。在变异之后?这可能不会保留原始列的顺序,但会将rel列附加到相应的val列之后。或者,如果要保持所有列的顺序,可以执行以下操作:选择1,{mut_cols=tailnames.,-1;cbindmut_cols[cT,F],mut_cols[cF,T]}谢谢,现在我自己找到了一种方法,使用一个helper函数来重新排序列以生成索引:interleaveColumns=functionv{c1,unlistsplit2:lengthv,1:lengthv-1/2,use.names=FALSE}然后一个简单的选择将执行%>%selectinterleaveColumns。
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
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
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