Bagaimana cara memotong spasi putih depan dan belakang?

360

Saya mengalami beberapa masalah dengan memimpin dan mengikuti spasi putih di data.frame. Misalnya saya ingin lihat tertentu rowdalam data.frameberdasarkan kondisi tertentu:

> myDummy[myDummy$country == c("Austria"),c(1,2,3:7,19)] 

[1] codeHelper     country        dummyLI    dummyLMI       dummyUMI       
[6] dummyHInonOECD dummyHIOECD    dummyOECD      
<0 rows> (or 0-length row.names)

Saya bertanya-tanya mengapa saya tidak mendapatkan hasil yang diharapkan karena negara Austria jelas ada di negara saya data.frame. Setelah melihat sejarah kode saya dan mencoba mencari tahu apa yang salah, saya mencoba:

> myDummy[myDummy$country == c("Austria "),c(1,2,3:7,19)]
   codeHelper  country dummyLI dummyLMI dummyUMI dummyHInonOECD dummyHIOECD
18        AUT Austria        0        0        0              0           1
   dummyOECD
18         1

Semua yang saya ubah dalam perintah adalah spasi tambahan setelah Austria.

Masalah menjengkelkan lebih lanjut jelas muncul. Misal ketika saya ingin menggabungkan dua frame berdasarkan kolom negara. Satu data.framemenggunakan "Austria "sementara bingkai lainnya "Austria". Pencocokan tidak berfungsi.

  1. Apakah ada cara yang bagus untuk 'menunjukkan' spasi putih di layar saya sehingga saya mengetahui masalahnya?
  2. Dan bisakah saya menghapus spasi putih terkemuka dan tertinggal di R?

Sejauh ini saya biasa menulis Perlskrip sederhana yang menghilangkan spasi, tetapi alangkah baiknya jika saya bisa melakukannya di dalam R.

mropa
sumber
1
Saya hanya melihat yang sub()menggunakan Perlnotasi juga. Maaf soal itu. Saya akan mencoba menggunakan fungsinya. Tetapi untuk pertanyaan pertama saya, saya belum punya solusi.
mropa
4
Seperti yang ditunjukkan Hadley, regex ini "^ \\ s + | \\ s + $" akan mengidentifikasi spasi putih terdepan dan tambahan. so x <- gsub ("^ \\ s + | \\ s + $", "", x) banyak fungsi baca R yang memiliki opsi ini: strip.white = FALSE
Jay

Jawaban:

456

Mungkin cara terbaik adalah menangani spasi putih tambahan saat Anda membaca file data Anda. Jika Anda menggunakan read.csvatau read.tableAnda dapat mengatur parameter strip.white=TRUE.

Jika Anda ingin membersihkan string setelahnya, Anda dapat menggunakan salah satu fungsi ini:

# returns string w/o leading whitespace
trim.leading <- function (x)  sub("^\\s+", "", x)

# returns string w/o trailing whitespace
trim.trailing <- function (x) sub("\\s+$", "", x)

# returns string w/o leading or trailing whitespace
trim <- function (x) gsub("^\\s+|\\s+$", "", x)

Untuk menggunakan salah satu fungsi ini di myDummy$country:

 myDummy$country <- trim(myDummy$country)

Untuk 'menunjukkan' spasi putih yang dapat Anda gunakan:

 paste(myDummy$country)

yang akan menunjukkan string yang dikelilingi oleh tanda kutip (") membuat spasi putih lebih mudah dikenali.

f3lix
sumber
7
Seperti yang ditunjukkan Hadley, regex ini "^ \\ s + | \\ s + $" akan mengidentifikasi spasi putih terdepan dan tambahan. so x <- gsub ("^ \\ s + | \\ s + $", "", x) banyak fungsi baca R yang memiliki opsi ini: strip.white = FALSE
Jay
50
Lihat juga str_trimdi stringrpaket.
Richie Cotton
1
Plus satu untuk "fungsi Potong sekarang disimpan untuk digunakan di masa depan" - terima kasih!
Chris Beeley
4
Sayangnya, strip.white = TRUE hanya berfungsi pada string yang tidak dikutip.
Rodrigo
2
Ada cara yang jauh lebih mudah untuk memotong spasi putih di R 3.2.0. Lihat jawaban selanjutnya!
Alex
519

Pada R 3.2.0, sebuah fungsi baru diperkenalkan untuk menghilangkan spasi putih depan / belakang:

trimws()

Lihat: http://stat.ethz.ch/R-manual/R-patched/library/base/html/trimws.html

wligtenberg
sumber
2
Itu tergantung pada definisi jawaban terbaik. Jawaban ini menyenangkan untuk diketahui (+1) tetapi dalam tes cepat, itu tidak secepat beberapa alternatif di luar sana.
A5C1D2H2I1M1N2O1R2T1
tampaknya tidak berfungsi untuk string multi-line, meskipun \nberada di kelas karakter tertutup. trimws("SELECT\n blah\n FROM foo;")masih berisi baris baru.
Jubbles
6
@ Jubbles Itulah perilaku yang diharapkan. Dalam string yang Anda berikan ke trimws tidak ada spasi putih awal atau akhir. Jika Anda ingin menghapus spasi putih awal dan akhir dari masing-masing garis dalam string, Anda harus membaginya terlebih dahulu. Seperti ini: trimws (strsplit ("SELECT \ n blah \ n FROM foo;", "\ n") [[1]])
wligtenberg
1
Meskipun fungsi bawaan untuk versi R terbaru, ia 'hanya' melakukan gaya regex PERL di bawah tenda. Saya mungkin mengharapkan beberapa kode C kustom cepat untuk melakukan ini. Mungkin trimwsregex cukup cepat. stringr::str_trim(berdasarkan stringi) juga menarik karena menggunakan pustaka string yang sepenuhnya diinternasionalkan yang sepenuhnya independen. Anda akan berpikir spasi putih akan kebal dari masalah dengan internasionalisasi, tapi saya ingin tahu. Saya belum pernah melihat perbandingan hasil asli vs stringr/ stringiatau tolok ukur apa pun.
Jack Wasey
Untuk beberapa alasan saya tidak tahu, trimws()tidak menghapus spasi putih utama saya, sementara Bryan di trim.strings()bawah ini (hanya 1 suara, milik saya!) ...
PatrickT
89

Untuk memanipulasi ruang putih, gunakan str_trim () dalam paket stringr. Paket ini memiliki manual bertanggal 15 Februari 2013 dan dalam CRAN. Fungsi ini juga dapat menangani vektor string.

install.packages("stringr", dependencies=TRUE)
require(stringr)
example(str_trim)
d4$clean2<-str_trim(d4$V2)

(kredit jatuh ke komentator: R. Cotton)

userJT
sumber
2
Solusi ini menghapus beberapa spasi putih mutan yang trimws()tidak dapat dihapus.
Richard Telford
1
@RichardTelford dapatkah Anda memberikan contoh? Karena itu mungkin dianggap bug dalam trimws.
wligtenberg
IMO ini adalah solusi terbaik. Tidak banyak kode dan berkinerja tinggi
Peter
Terima kasih telah meminta (stringr) dokumentasi atau contoh mereka tidak memiliki baris kode yang diperlukan ini!
pgee70
23

Fungsi sederhana untuk menghapus spasi putih depan dan belakang:

trim <- function( x ) {
  gsub("(^[[:space:]]+|[[:space:]]+$)", "", x)
}

Pemakaian:

> text = "   foo bar  baz 3 "
> trim(text)
[1] "foo bar  baz 3"
Bernhard Kausler
sumber
11

ad1) Untuk melihat spasi putih Anda bisa langsung menelepon print.data.framedengan argumen yang dimodifikasi:

print(head(iris), quote=TRUE)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width  Species
# 1        "5.1"       "3.5"        "1.4"       "0.2" "setosa"
# 2        "4.9"       "3.0"        "1.4"       "0.2" "setosa"
# 3        "4.7"       "3.2"        "1.3"       "0.2" "setosa"
# 4        "4.6"       "3.1"        "1.5"       "0.2" "setosa"
# 5        "5.0"       "3.6"        "1.4"       "0.2" "setosa"
# 6        "5.4"       "3.9"        "1.7"       "0.4" "setosa"

Lihat juga ?print.data.frameuntuk opsi lain.

Marek
sumber
9

Gunakan grep atau grepl untuk menemukan pengamatan dengan spasi putih dan sub untuk menyingkirkannya.

names<-c("Ganga Din\t","Shyam Lal","Bulbul ")
grep("[[:space:]]+$",names)
[1] 1 3
grepl("[[:space:]]+$",names)
[1]  TRUE FALSE  TRUE
sub("[[:space:]]+$","",names)
[1] "Ganga Din" "Shyam Lal" "Bulbul"  
Jyotirmoy Bhattacharya
sumber
7
Atau, sedikit lebih ringkas,"^\\s+|\\s+$"
hadley
4
Hanya ingin menunjukkan, bahwa seseorang harus menggunakan gsubalih-alih subdengan regexp hadley. Dengan subitu akan menghapus trailing whitespace hanya jika tidak ada whitespace terkemuka ...
f3lix
Tidak tahu Anda bisa menggunakan dll dengan perl = FALSE. Dokumen mengatakan bahwa sintaks POSIX digunakan dalam kasus itu, tetapi sintaksis yang diterima sebenarnya adalah superset yang didefinisikan oleh perpustakaan reg
Jyotirmoy Bhattacharya
5

Saya lebih suka menambahkan jawaban sebagai komentar untuk pengguna56 tetapi belum dapat menulis sebagai jawaban independen. Menghapus blanking leading dan trailing dapat dicapai melalui fungsi trim () dari paket gdata juga:

require(gdata)
example(trim)

Contoh penggunaan:

> trim("   Remove leading and trailing blanks    ")
[1] "Remove leading and trailing blanks"
KAA
sumber
5

Masalah terkait lainnya terjadi jika Anda memiliki beberapa spasi di antara input:

> a <- "  a string         with lots   of starting, inter   mediate and trailing   whitespace     "

Anda kemudian dapat dengan mudah membagi string ini menjadi token "nyata" menggunakan ekspresi reguler ke splitargumen:

> strsplit(a, split=" +")
[[1]]
 [1] ""           "a"          "string"     "with"       "lots"      
 [6] "of"         "starting,"  "inter"      "mediate"    "and"       
[11] "trailing"   "whitespace"

Perhatikan bahwa jika ada kecocokan di awal string (tidak kosong), elemen pertama dari output adalah '""', tetapi jika ada kecocokan di akhir string, outputnya sama dengan dengan pertandingan dihapus.

TMOTTM
sumber
5

Opsi lain adalah menggunakan stri_trimfungsi dari stringipaket yang defaultnya untuk menghapus spasi putih depan dan akhir:

> x <- c("  leading space","trailing space   ")
> stri_trim(x)
[1] "leading space"  "trailing space"

Untuk hanya menghapus spasi putih terkemuka, gunakan stri_trim_left. Untuk hanya menghapus spasi spasi, gunakan stri_trim_right. Saat Anda ingin menghapus karakter utama atau karakter lainnya, Anda harus menentukannya dengan pattern =.

Lihat juga ?stri_trimuntuk info lebih lanjut.

Jaap
sumber
2

Saya membuat trim.strings ()fungsi untuk memangkas spasi memimpin dan / atau mengikuti spasi sebagai:

# Arguments:    x - character vector
#            side - side(s) on which to remove whitespace 
#                   default : "both"
#                   possible values: c("both", "leading", "trailing")

trim.strings <- function(x, side = "both") { 
    if (is.na(match(side, c("both", "leading", "trailing")))) { 
      side <- "both" 
      } 
    if (side == "leading") { 
      sub("^\\s+", "", x)
      } else {
        if (side == "trailing") {
          sub("\\s+$", "", x)
    } else gsub("^\\s+|\\s+$", "", x)
    } 
} 

Untuk ilustrasi,

a <- c("   ABC123 456    ", " ABC123DEF          ")

# returns string without leading and trailing whitespace
trim.strings(a)
# [1] "ABC123 456" "ABC123DEF" 

# returns string without leading whitespace
trim.strings(a, side = "leading")
# [1] "ABC123 456    "      "ABC123DEF          "

# returns string without trailing whitespace
trim.strings(a, side = "trailing")
# [1] "   ABC123 456" " ABC123DEF"   
Bryan
sumber
1

Metode terbaik adalah trimws ()

Kode berikut akan menerapkan fungsi ini ke seluruh kerangka data

mydataframe <- data.frame (lapply (mydataframe, trimws), stringsAsFactors = FALSE)

Santosh Kadge
sumber
atau df[] <- lapply(df, trimws)agar lebih kompak. Tetapi dalam kedua kasus akan memaksa kolom untuk karakter. df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)Supaya aman.
Moody_Mudskipper
1

Saya mencoba trim (). Berfungsi dengan baik dengan spasi putih dan juga '\ n'. x = '\ n Harden, J. \ n'

trim (x)

J.Dan
sumber
0
myDummy[myDummy$country == "Austria "] <- "Austria"

Setelah ini, Anda harus memaksa R untuk tidak mengenali "Austria" sebagai level. Anggap Anda juga memiliki level "AS" dan "Spanyol":

myDummy$country = factor(myDummy$country, levels=c("Austria", "USA", "Spain"))

Sedikit kurang mengintimidasi daripada respons suara tertinggi, tetapi tetap harus bekerja.

David Mitchell
sumber