2016-07-13 255 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="_")