วิธีการตัดช่องว่างชั้นนำและต่อท้าย?


360

ฉันมีปัญหากับช่องว่างนำหน้าและต่อท้ายใน data.frame เช่นฉันชอบที่จะดูเฉพาะrowในdata.frameตามเงื่อนไขบางอย่าง:

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

ฉันสงสัยว่าทำไมฉันไม่ได้รับผลลัพธ์ที่คาดหวังเนื่องจากประเทศออสเตรียมีอยู่ในตัวฉันdata.frameอย่างชัดเจน หลังจากดูประวัติรหัสของฉันและพยายามหาสิ่งที่ผิดพลาดฉันพยายาม:

> 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

ทั้งหมดที่ฉันมีการเปลี่ยนแปลงในคำสั่งเป็นช่องว่างเพิ่มเติมหลังจากออสเตรีย

ปัญหาที่น่ารำคาญเพิ่มเติมอย่างเห็นได้ชัดเกิดขึ้น เช่นเมื่อฉันต้องการรวมสองเฟรมตามคอลัมน์ประเทศ หนึ่งdata.frameใช้"Austria "ในขณะที่กรอบอื่น ๆ "Austria"ที่มี การจับคู่ไม่ทำงาน

  1. มีวิธีที่ดีในการ 'แสดง' ช่องว่างบนหน้าจอของฉันเพื่อให้ฉันตระหนักถึงปัญหาหรือไม่
  2. และฉันสามารถลบช่องว่างนำหน้าและต่อท้ายใน R ได้หรือไม่

จนถึงตอนนี้ฉันเคยเขียนPerlสคริปต์ง่าย ๆซึ่งลบช่องว่างออก แต่มันคงจะดีถ้าฉันสามารถทำมันได้ในอาร์


1
ฉันเพิ่งเห็นว่าsub()ใช้Perlสัญกรณ์เช่นกัน ขอโทษด้วยกับเรื่องนั้น. ฉันจะลองใช้ฟังก์ชั่นนี้ แต่สำหรับคำถามแรกของฉันฉันยังไม่มีวิธีแก้ปัญหา
mropa

4
ดังที่แฮดลี่ย์ชี้มัน regex นี้ "^ \\ s + | \\ s + $" จะระบุช่องว่างนำหน้าและตามหลัง ดังนั้น x <- gsub ("^ \\ s + | \\ s + $", "", x) ฟังก์ชั่นการอ่านจำนวนมากของ R เช่นเดียวกับตัวเลือกนี้: strip.white = FALSE
Jay

คำตอบ:


456

อาจเป็นวิธีที่ดีที่สุดคือการจัดการช่องว่างต่อท้ายเมื่อคุณอ่านไฟล์ข้อมูลของคุณ ถ้าคุณใช้read.csvหรือคุณสามารถตั้งค่าพารามิเตอร์read.tablestrip.white=TRUE

หากคุณต้องการล้างสตริงหลังจากนั้นคุณสามารถใช้หนึ่งในฟังก์ชันเหล่านี้:

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

หากต้องการใช้หนึ่งในฟังก์ชันเหล่านี้กับmyDummy$country:

 myDummy$country <- trim(myDummy$country)

หากต้องการ 'แสดง' ช่องว่างที่คุณสามารถใช้ได้:

 paste(myDummy$country)

ซึ่งจะแสดงให้คุณเห็นสตริงที่ล้อมรอบด้วยเครื่องหมายคำพูด (") ทำให้การมองเห็นช่องว่างง่ายขึ้น


7
ดังที่แฮดลี่ย์ชี้มัน regex นี้ "^ \\ s + | \\ s + $" จะระบุช่องว่างนำหน้าและตามหลัง ดังนั้น x <- gsub ("^ \\ s + | \\ s + $", "", x) ฟังก์ชั่นการอ่านจำนวนมากของ R เช่นเดียวกับตัวเลือกนี้: strip.white = FALSE
Jay

50
ดูเพิ่มเติมstr_trimในstringrแพ็คเกจ
Richie Cotton

1
บวกหนึ่งสำหรับ "ฟังก์ชั่น Trim ตอนนี้เก็บไว้เพื่อใช้ในอนาคต" - ขอบคุณ!
Chris Beeley

4
น่าเสียดายที่ strip.white = TRUE ใช้ได้กับสตริงที่ไม่ได้ยกมาเท่านั้น
Rodrigo

2
มีวิธีที่ง่ายกว่าในการตัดช่องว่างใน R 3.2.0 ดูคำตอบต่อไป!
อเล็กซ์

519

ตั้งแต่ R 3.2.0 มีการแนะนำฟังก์ชั่นใหม่สำหรับการลบช่องว่างนำหน้า / ต่อท้าย:

trimws()

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


2
ขึ้นอยู่กับคำจำกัดความของคำตอบที่ดีที่สุด คำตอบนี้ดีที่จะรู้ (+1) แต่ในการทดสอบอย่างรวดเร็วมันไม่เร็วเท่าทางเลือกอื่น ๆ
A5C1D2H2I1M1N2O1R2T1

ดูเหมือนจะไม่ทำงานสำหรับสตริงหลายบรรทัดแม้จะ\nอยู่ในคลาสอักขระที่ครอบคลุม trimws("SELECT\n blah\n FROM foo;")ยังมีการขึ้นบรรทัดใหม่
Jubbles

6
@ Jubbles นั่นคือพฤติกรรมที่คาดหวัง ในสตริงที่คุณส่งผ่านไปยัง trimws ไม่มีช่องว่างนำหน้าหรือต่อท้ายสีขาว หากคุณต้องการลบช่องว่างนำหน้าและต่อท้ายออกจากแต่ละบรรทัดในสตริงคุณจะต้องแยกมันออกก่อน เช่นนี้: trimws (strsplit ("เลือก \ n blah \ n จาก foo;", "\ n") [[1]])
wligtenberg

1
แม้ว่าฟังก์ชั่นบิวท์อินสำหรับ R รุ่นล่าสุด แต่มัน 'เพียงแค่' ทำรูปแบบ PERL ภายใต้ประทุน ฉันอาจคาดว่าจะมีรหัส C ที่กำหนดเองที่รวดเร็วสำหรับการทำเช่นนี้ บางทีtrimwsregex นั้นเร็วพอ stringr::str_trim(ขึ้นอยู่กับstringi) ก็น่าสนใจที่จะใช้ไลบรารี่ไลบรารี่ที่เป็นสากลอย่างสมบูรณ์ คุณคิดว่าช่องว่างจะได้รับการยกเว้นจากปัญหาเกี่ยวกับความเป็นสากล แต่ฉันสงสัยว่า ฉันไม่เคยเห็นการเปรียบเทียบผลลัพธ์ของ native vs stringr/ stringiหรือการวัดประสิทธิภาพใด ๆ
Jack Wasey

ด้วยเหตุผลบางอย่างที่ฉันไม่สามารถเข้าใจtrimws()ได้อย่าลบช่องว่างสีขาวนำของฉันในขณะที่ไบรอันtrim.strings()ด้านล่าง (เพียง 1 โหวตฉัน!) ได้ ...
PatrickT

89

หากต้องการจัดการพื้นที่ว่างให้ใช้ str_trim () ในแพ็คเกจ stringr แพ็คเกจมีคู่มือลงวันที่ 15 กุมภาพันธ์ 2556 และอยู่ใน CRAN ฟังก์ชั่นยังสามารถจัดการกับเวกเตอร์สตริง

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

(เครดิตไปที่ commenter: R. Cotton)


2
วิธีการนี้จะลบช่องว่างกลายพันธุ์บางส่วนที่trimws()ไม่สามารถลบได้
Richard Telford

1
@RichardTelford คุณสามารถแสดงตัวอย่างได้หรือไม่ เพราะนั่นอาจถือเป็นข้อผิดพลาดใน trimws
wligtenberg

IMO นี่เป็นทางออกที่ดีที่สุด ไม่ค่อยมีโค้ดและมีประสิทธิภาพสูงเท่าไหร่
Peter

ขอบคุณสำหรับความต้องการ (stringr) เอกสารหรือตัวอย่างของพวกเขาไม่มีบรรทัดของรหัสที่ต้องการ!
pgee70

23

ฟังก์ชั่นง่าย ๆในการลบช่องว่างนำหน้าและต่อท้าย:

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

การใช้งาน:

> text = "   foo bar  baz 3 "
> trim(text)
[1] "foo bar  baz 3"

11

ad1) หากต้องการดูช่องว่างสีขาวคุณสามารถโทรหาprint.data.frameด้วยอาร์กิวเมนต์ที่แก้ไขได้โดยตรง:

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"

ดูเพิ่มเติม?print.data.frameสำหรับตัวเลือกอื่น ๆ


9

ใช้ grep หรือ grepl เพื่อค้นหาสิ่งที่สังเกตด้วย whitespaces และ sub เพื่อกำจัดมัน

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"  

7
หรือพูดให้ชัดขึ้นนิดหน่อย"^\\s+|\\s+$"
Hadley

4
แค่อยากจะชี้ให้เห็นว่าจะต้องใช้gsubแทนsubregexp ของ hadley ด้วยsubมันจะตัดช่องว่างต่อท้ายเฉพาะในกรณีที่ไม่มีช่องว่างนำ ...
f3lix

ไม่ทราบว่าคุณสามารถใช้ \ s ฯลฯ กับ perl = FALSE เอกสารบอกว่ามีการใช้ไวยากรณ์ POSIX ในกรณีนั้น แต่ไวยากรณ์ที่ยอมรับนั้นจริง ๆ แล้วเป็น superset ที่กำหนดโดยไลบรารี TRE regex laurikari.net/tre/documentation/regex-syntax
Jyotirmoy Bhattacharya

5

ฉันต้องการเพิ่มคำตอบเป็นความคิดเห็นให้กับ user56 แต่ยังไม่สามารถเขียนเป็นคำตอบอิสระได้ การลบช่องว่างนำหน้าและต่อท้ายอาจทำได้โดยใช้ฟังก์ชัน trim () จากแพ็คเกจ gdata เช่นกัน:

require(gdata)
example(trim)

ตัวอย่างการใช้งาน:

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

5

ปัญหาอื่นที่เกี่ยวข้องเกิดขึ้นหากคุณมีช่องว่างหลายช่องในระหว่างอินพุต:

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

จากนั้นคุณสามารถแยกสตริงนี้เป็นโทเค็น "ของจริง" ได้อย่างง่ายดายโดยใช้นิพจน์ทั่วไปกับsplitอาร์กิวเมนต์:

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

โปรดทราบว่าหากมีการจับคู่ที่จุดเริ่มต้นของสตริง (ไม่ว่าง) องค์ประกอบแรกของเอาต์พุตคือ '"" "แต่ถ้ามีการจับคู่ที่ส่วนท้ายของสตริงเอาต์พุตจะเหมือนกับ เมื่อการแข่งขันถูกลบ


5

ตัวเลือกอื่นคือการใช้stri_trimฟังก์ชั่นจากstringiแพคเกจซึ่งเป็นค่าเริ่มต้นเพื่อลบช่องว่างนำหน้าและต่อท้าย:

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

stri_trim_leftเพียงลบช่องว่างชั้นนำใช้ สำหรับการลบช่องว่างต่อท้ายให้ใช้stri_trim_rightเท่านั้น เมื่อคุณต้องการที่จะลบชั้นนำอื่น ๆ pattern =หรือตัวอักษรต่อท้ายคุณจะต้องระบุว่า

ดูเพิ่มเติมที่?stri_trimสำหรับข้อมูลเพิ่มเติม


2

ฉันสร้างtrim.strings ()ฟังก์ชั่นเพื่อตัดขอบชั้นนำและ / หรือช่องว่างต่อท้ายดังนี้

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

สำหรับภาพประกอบ

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"   

1

วิธีที่ดีที่สุดคือ trimws ()

รหัสต่อไปนี้จะใช้ฟังก์ชั่นนี้กับดาต้าเฟรมทั้งหมด

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


หรือdf[] <- lapply(df, trimws)จะกะทัดรัดกว่า แต่ในทั้งสองกรณีจะบังคับคอลัมน์ให้เป็นอักขระ df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)เพื่อความปลอดภัย.
Moody_Mudskipper

1

ฉันลองตัด () ทำงานได้ดีกับช่องว่างสีขาวเช่นเดียวกับ '\ n' x = '\ n แข็ง, J. \ n'

ตัด (x)


0
myDummy[myDummy$country == "Austria "] <- "Austria"

หลังจากนี้คุณจะต้องบังคับให้ R ไม่รู้จัก "ออสเตรีย" เป็นระดับ สมมติว่าคุณมี "USA" และ "Spain" เป็นเลเวลด้วย:

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

ขู่เข็ญน้อยกว่าคำตอบโหวตสูงสุด แต่ก็ควรทำงาน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.