2016-07-13 200 views
2

我有一个数据集,其中包括一堆与我要制作成各种前缀后缀的变量。数据集还包含一些没有任何后缀的变量。喜欢的东西:setNames后缀前缀

df <- data.frame(
    home_loc = rnorm(5), 
    work_loc = rnorm(5), 
    x1   = rnorm(5), 
    walk_act = rnorm(5), 
    bike_act = rnorm(5), 
    x2   = rnorm(5), 
    happy_yest = rnorm(5), 
    sad_yest = rnorm(5) 
) 

我能想出以下解决方案:

suff_to_pre <- function(x, suffix, prefix) { 
    for (i in seq_along(names(x))) { 
    if (grepl(suffix, names(x)[i])) { 
     names(x)[i] <- sub(suffix, "", names(x)[i]) 
     names(x)[i] <- paste0(prefix, names(x)[i]) 
    } 
    } 
    names(x) 
} 

names(df) <- suff_to_pre(df, suffix = "_loc", prefix = "loc_") 
names(df) <- suff_to_pre(df, suffix = "_act", prefix = "act_") 
names(df) <- suff_to_pre(df, suffix = "_yest", prefix = "yest_") 

names(df) 
[1] "loc_home" "loc_work" "x1" "act_walk" "act_bike" "x2" "yest_happy" 
[8] "yest_sad" 

但是,我感觉不很满意。具体来说,我真的很喜欢使用dplyr获得相同结果的方法。 I found thisthis,该拉去:

a <- df %>% 
    select(ends_with("_loc")) %>% 
    setNames(sub("_loc", "", names(.))) %>% 
    setNames(paste0("loc_", names(.))) 

b <- df %>% 
    select(ends_with("_act")) %>% 
    setNames(sub("_act", "", names(.))) %>% 
    setNames(paste0("act_", names(.))) 

c <- df %>% 
    select(ends_with("_yest")) %>% 
    setNames(sub("_yest", "", names(.))) %>% 
    setNames(paste0("yest_", names(.))) 

df <- cbind(
    select(df, x1, x2), a, b, c 
) 

这显然是不理想的。我希望有人提出使用dplyr更优雅的解决方案。

编辑
@docendo discimus和@ zx8754了真正有用的答案,但我应该更加明确。我也有包含下划线的变量,但不是我想更改为前缀的后缀。

为例(见下free_time):

df <- data.frame(
     home_loc = rnorm(5), 
     work_loc = rnorm(5), 
     x_1  = rnorm(5), 
     walk_act = rnorm(5), 
     bike_act = rnorm(5), 
     x_2  = rnorm(5), 
     happy_yest = rnorm(5), 
     sad_yest = rnorm(5), 
     free_time = rnorm(5) 
) 

回答

4

sub调用应该是足够了:

sub("^(.*)_(.*)$", "\\2_\\1", names(df)) 
#[1] "loc_home" "loc_work" "x1"   "act_walk" "act_bike" "x2"   "yest_happy" "yest_sad" 

当然并更改名称,分配回:

names(df) <- sub("^(.*)_(.*)$", "\\2_\\1", names(df)) 

而且在dplyr管你可以使用setNames

df %>% setNames(sub("^(.*)_(.*)$", "\\2_\\1", names(.))) 

模式"^(.*)_(.*)$"创建两个捕获组,一个在下划线之前,另一个在下一个之后。在替换"\\2_\\1"中,我们告诉R首先提取第二个组,然后使用下划线和finnaly作为后缀前缀的第一个组。但是,如果在条目中未找到带下划线的模式,则不会有任何更改。问题更新后

更新:

对于稍微复杂的情况下,您可以执行以下操作:

1)存储需要更改为前缀的所有后缀:

suf <- c("act", "loc", "yest") 

2)创建基于后缀的正则表达式模式:

pat <- paste0("^(.*)_(", paste(suf, collapse = "|"), ")$") 
pat 
#[1] "^(.*)_(act|loc|yest)$" 

3)之前进行:

sub(pat, "\\2_\\1", names(df)) 
# [1] "loc_home" "loc_work" "x_1"  "act_walk" "act_bike" "x_2"  "yest_happy" "yest_sad" "free_time" 

df %>% setNames(sub(pat, "\\2_\\1", names(.))) 
+0

意想不到的答案用这个,但是我本来应该更明确。我也有包含下划线的变量,但不是我想更改为前缀(例如,free_time)的后缀。 –

+0

这个答案非常明确且有帮助。谢谢。显然我需要学习正则表达式。 –

1

我们可以使用str_replacestringr。这里的想法是使用捕捉模式作为一个组,即在(..)之内。第一个捕获组(([^_])*)表示零个或多个不是_的字符,然后是_,然后是另一个捕获组(([^_])),在替换中我们只是切换反向引用。

library(stringr) 
names(df) <- str_replace(names(df), "^([^_]*)_([^_]*)$", "\\2_\\1") 
names(df) 
#[1] "loc_home" "loc_work" "x1"   "act_walk" 
#[5] "act_bike" "x2"   "yest_happy" "yest_sad" 

如果我们需要用管道

library(magrittr) 
df %<>% 
    setNames(str_replace(names(.), "^([^_]*)_([^_]*)$", "\\2_\\1")) 

使用或不使用任何正则表达式

sapply(sapply(strsplit(names(df), "_"), rev), paste, collapse="_")