2017-04-01 57 views
0

我们有一个数据框。带有匿名函数的mutate_at

df <- data_frame(x = 1:5, y = 101:105) 

和其操作上的柱,并返回一个函数若干列

ff <- function(df, col) df %>% 
     mutate_at(col, funs(c1 = .*2, c2 = .*3, c3 = .*4)) 

如何可以替代硬编码列名C1,C2,C3与从参数col例如构造名paste0(col, 1)

这样

df %>% ff("x") 

返回与

# A tibble: 10 × 5 
     x  y x1 x2 x3 
    <int> <int> <dbl> <dbl> <dbl> 
1  1 100  2  3  4 
2  2 101  4  6  8 
3  3 102  6  9 12 
4  4 103  8 12 16 
5  5 104 10 15 20 
+1

非dplyr解决方案可以是简单地'DF [paste0( “X”,1:3)] < - DF $ X *代表(2:4中,每个=长度( df $ x))'(可以很容易地包装成一个函数) –

回答

2

一个tibble您可以采取的rename_优势,通过它,你可以很容易地构建名称。在这里,我将名称设置为与使用setNames的硬编码名称相匹配,然后重命名它们。

updatedFF <- function(df, col){ 
    colNames <- 
    setNames(
     paste0("c", 1:3) 
     , paste0(col, 1:3)) 

    df %>% 
    mutate_at(col, funs(c1 = .*2, c2 = .*3, c3 = .*4)) %>% 
    rename_(.dots = colNames) 
} 

df %>% updatedFF("x") 

# A tibble: 5 × 5 
     x  y x1 x2 x3 
    <int> <int> <dbl> <dbl> <dbl> 
1  1 101  2  3  4 
2  2 102  4  6  8 
3  3 103  6  9 12 
4  4 104  8 12 16 
5  5 105 10 15 20 

需要注意的是,如果你在一个以上的列名通过这将会失败。这是因为当你传入一个列名称时,已命名的函数会预先加上列名。你可以在你原有的ff功能看这个,如果你通过这两个“X”和“Y”:

df %>% ff(c("x", "y")) 

# A tibble: 5 × 8 
     x  y x_c1 y_c1 x_c2 y_c2 x_c3 y_c3 
    <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  1 101  2 202  3 303  4 404 
2  2 102  4 204  6 306  8 408 
3  3 103  6 206  9 309 12 412 
4  4 104  8 208 12 312 16 416 
5  5 105 10 210 15 315 20 420 

这种差异可能偶尔会出现问题,所以你可能想确保即使仅使用一列,也可以通过设置名称使其包含列名来一致地处理它。在这里,如果只有一列获得通过,也只复位名称和它设置它们相匹配时,多列在传递时发生的格式。

​​

有一列,其前(虽然工作原理非常类似于“ _c”包括):

df %>% moreComplexFF(c("x")) 

 x  y x_c1 x_c2 x_c3 
    <int> <int> <dbl> <dbl> <dbl> 
1  1 101  2  3  4 
2  2 102  4  6  8 
3  3 103  6  9 12 
4  4 104  8 12 16 
5  5 105 10 15 20 

有两列,它留下的名字单独(因此不会引发错误):

df %>% moreComplexFF(c("x", "y")) 

给出

 x  y x_c1 y_c1 x_c2 y_c2 x_c3 y_c3 
    <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  1 101  2 202  3 303  4 404 
2  2 102  4 204  6 306  8 408 
3  3 103  6 206  9 309 12 412 
4  4 104  8 208 12 312 16 416 
5  5 105 10 210 15 315 20 420