2014-09-23 8 views
5

Mam dwie ramki danych z kolumną o nazwie "Tytuł" w każdym, zawierające ciąg. Muszę zmniejszyć te struny, aby je połączyć. Teraz chcę uczynić to tak czystym, jak to możliwe w pętli tak, że będę musiał tylko raz napisać funkcję gsub.gsub() na wielu ramkach danych w pętli/lapply

Powiedzmy mam:

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

oraz:

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

Chciałbym teraz uruchomić:

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

Próbowałem następującą pętlę:

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

ale to nie działa - pomimo braku komunikatów o błędach.

Myślałem również o lapply(list(dt_1, dt_2), function(w){ w$Title <- XXX }), ale nie wiem, co umieścić w XXX, ponieważ gsub() potrzebuje jako trzeci argument listę ciągów.

+1

'lapply (lista (df_1, df_2), funkcja (w) gsub (" | \\. | '|: |! | \\' | _ "," ", w $ Tytuł))'? Lub bardziej ogólny "lapply (mget (ls (pattern =" df _ \\ d ")), function (w) gsub (" | \\. | '|: |! | \\' | _ "," ", w $ Title)) ' –

+0

Wyrażenie regularne' [. ':! _] 'Jest nieco łatwiejsze do odczytania. –

+1

To 'assign (paste0 (dtfrm," $ Title ")' nie zadziała, ponieważ masz nadzieję, że 'assign' zinterpretuje wynik znaku jako obiekt języka i nie jest skonfigurowany do tego. –

Odpowiedz

1

to działa:

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

Testowanie:

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

I:

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

get() pozwoli na programowe pobieranie wielu zestawów danych.
data.table() będą pomocne w modyfikacji kolumn w każdym z łatwością

## 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

Gdzieś pomiędzy @ komentarz Dawida i @ odpowiedź Carlosa, z odrobiną dodatkowej:

Zastosowanie mget aby chwycić data.frame s, a list2env skopiować na oryginalnych data.frame s, jeśli jest to pożądane.

mget + lapply zrobi transformację ....

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 

... ale wynik pozostaje w list i nie wpływa na oryginalne 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 

Jeśli chcesz nadpisać data.frame s, spróbuj:

+0

+1 dla czystego i szybkiego kodu. Uwaga: Jeśli ktoś ma wzorzec nazwy, który nie robi ' t pozwól 'ls()', użyj 'mget (c (" df_1 "," 2ndftrm "))'. – MERose