2014-09-23 2 views
5

У меня есть два кадра данных с колонкой с названием «Заголовок» в каждой, содержащей строку. Мне нужно уменьшить эти строки, чтобы объединить их. Теперь я хочу сделать это как можно чище в цикле, так что мне нужно только один раз написать gsub-функцию.gsub() на нескольких кадрах данных в loop/lapply

Скажем, у меня есть:

df_1 <-read.table(text=" 
id Title 
1 some_average_title 
2 another:_one 
3 the_third! 
4 and_'the'_last 
",header=TRUE,sep="") 

и:

df_2 <-read.table(text=" 
id Title 
1 some_average.title 
2 another:one 
3 the_third 
4 and_the_last 
",header=TRUE,sep="") 

Я бы сейчас работать:

df_1$Title <- gsub(" |\\.|'|:|!|\\'|_", "", df_1$Title) 
df_2$Title <- gsub(" |\\.|'|:|!|\\'|_", "", df_2$Title) 

Я попробовал следующий цикл:

for (dtfrm in c("dt_1", "df_2")) { 
    assign(paste0(dtfrm, "$Title"), 
    gsub(" |\\.|'|:|!|\\'|", "", get(paste0(dtfrm, "$Title"))) 
    ) 
    } 

, но он не работает - несмотря на отсутствие сообщений об ошибках.

Я также думал о lapply(list(dt_1, dt_2), function(w){ w$Title <- XXX }), но я не знаю, что поставить для XXX, потому что gsub() нуждается в третьем аргументе в списке строк.

+1

'lapply (list (df_1, df_2), function (w) gsub (" | \\. | '|: |! | \\' | _ "," ", w $ Title))'? Или более общий 'lapply (mget (ls (pattern =" df _ \\ d ")), функция (w) gsub (" | \\. | '|: |! | \\' | _ "," ", w $ Title)) ' –

+0

Регулярное выражение' [. ':! _] 'Немного легче читать. –

+1

Это 'assign (paste0 (dtfrm," $ Title ")' не будет работать, потому что вы надеетесь, что 'assign' интерпретирует результат символа как объект языка, и он не настроен для этого. –

ответ

1

Это работает:

for(df in c("df_1", "df_2")){ 
    assign(df, transform(get(df), Title = gsub(" |\\.|'|:|!|\\'|_", "", Title))) 
} 

Тестирование:

df_1 
    id   Title 
1 1 someaveragetitle 
2 2  anotherone 
3 3   thethird 
4 4  andthelast 

И:

df_2 
    id   Title 
1 1 someaveragetitle 
2 2  anotherone 
3 3   thethird 
4 4  andthelast 
0

get() позволит вам программно захватывать ваши многочисленные наборы данных.
data.table() будет полезно в изменении столбцов в каждой с легкостью

## CREATING A FEW MORE DATA SETS 
df_3 <- df_2 
df_4 <- df_1 
set.seed(1) 
df_3$id <- sample(20, 4) 
df_4$id <- sample(20, 4) 

library(data.table) 

dt_1 <- as.data.table(df_1) 
dt_2 <- as.data.table(df_2) 
dt_3 <- as.data.table(df_3) 
dt_4 <- as.data.table(df_4) 

## OR programatically: 

Numb_of_DTs <- 4 

names_of_dt_objects <- paste("dt", 1:Numb_of_DTs, sep="_") # dt_1, dt_2, etc 
names_of_df_objects <- paste("df", 1:Numb_of_DTs, sep="_") # dt_1, dt_2, etc 

for (i in 1:Numb_of_DTs) 
    assign(names_of_dt_objects[[i]], as.data.table(get(namse(names_of_df_objects[[i]])))) 


for (dt.nm in names_of_dt_objects) { 
    get(dt.nm)[, Title := gsub("[ .':!_]", "", Title)] 
    ## set the key for merging in the next step 
    setkey(get(dt.nm), Title) 
    ## You might want to insert a line to clean up the column names, using 
    ## setnames(get(dt.nm), OLD_NAMES, NEW_NAMES) 
} 


Reduce(merge, lapply(names_of_dt_objects, function(x) get(x))) 
1

Где-то между @ комментарий Давида и @ ответ Карлоса, с немного дополнительных:

Используйте mget, чтобы захватить ваши data.frame с, а list2env скопировать оригинальные data.frame с, если это необходимо.

mget + lapply будет делать преобразование ....

lapply(mget(ls(pattern = "df_\\d")), function(w) 
    transform(w, Title = gsub(" |\\.|'|:|!|\\'|_", "", Title))) 
# $df_1 
# id   Title 
# 1 1 someaveragetitle 
# 2 2  anotherone 
# 3 3   thethird 
# 4 4  andthelast 
# 
# $df_2 
# id   Title 
# 1 1 someaveragetitle 
# 2 2  anotherone 
# 3 3   thethird 
# 4 4  andthelast 

... но результат остается в list и не влияет на оригинальные data.frame S:

# df_1 
# id    Title 
# 1 1 some_average_title 
# 2 2  another:_one 
# 3 3   the_third! 
# 4 4  and_'the'_last 

Если вы хотели бы переписать data.frame s, попробуйте:

list2env(
    lapply(mget(ls(pattern = "df_\\d")), function(w) 
    transform(w, Title = gsub(" |\\.|'|:|!|\\'|_", "", Title))), 
    envir = .GlobalEnv) 
df_1 
# id   Title 
# 1 1 someaveragetitle 
# 2 2  anotherone 
# 3 3   thethird 
# 4 4  andthelast 
+0

+1 для чистого и быстрого кода. Примечание: Если у кого-то есть шаблон имени, t разрешить 'ls()', использовать 'mget (c (" df_1 "," 2ndftrm "))'. – MERose