Làm thế nào để cắt khoảng trắng hàng đầu và dấu?


360

Tôi đang gặp một số rắc rối với khoảng trắng hàng đầu và dấu trong một data.frame. Ví dụ: Tôi muốn có một cái nhìn tại một cụ thể rowtrong một data.framedựa trên một điều kiện nhất định:

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

Tôi đã tự hỏi tại sao tôi không nhận được sản lượng như mong đợi vì đất nước Áo rõ ràng tồn tại trong tôi data.frame. Sau khi xem qua lịch sử mã của tôi và cố gắng tìm ra những gì đã sai, tôi đã thử:

> 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

Tất cả những gì tôi đã thay đổi trong lệnh là một khoảng trắng bổ sung sau Áo.

Vấn đề khó chịu hơn rõ ràng phát sinh. Ví dụ: khi tôi muốn hợp nhất hai khung dựa trên cột quốc gia. Một data.framesử dụng "Austria "trong khi các khung khác có "Austria". Sự phù hợp không hoạt động.

  1. Có cách nào hay để 'hiển thị' khoảng trắng trên màn hình của tôi để tôi nhận thức được vấn đề không?
  2. Và tôi có thể xóa khoảng trắng hàng đầu và dấu trong R không?

Cho đến nay tôi đã từng viết một Perlkịch bản đơn giản giúp loại bỏ khoảng trắng nhưng thật tuyệt nếu tôi có thể làm điều đó bằng cách nào đó bên trong R.


1
Tôi chỉ thấy rằng sub()sử dụng Perlký hiệu là tốt. Xin lỗi vì điều đó. Tôi sẽ cố gắng sử dụng chức năng. Nhưng đối với câu hỏi đầu tiên của tôi, tôi chưa có giải pháp.
mropa

4
Như hadley đã chỉ ra regex này "^ \\ s + | \\ s + $" sẽ xác định khoảng trắng hàng đầu và dấu. vì vậy x <- gsub ("^ \\ s + | \\ s + $", "", x) nhiều hàm đọc của R có tùy chọn này: dải.white = FALSE
Jay

Câu trả lời:


456

Có lẽ cách tốt nhất là xử lý các khoảng trắng ở cuối khi bạn đọc tệp dữ liệu của mình. Nếu bạn sử dụng read.csvhoặc read.tablebạn có thể đặt tham số strip.white=TRUE.

Nếu bạn muốn xóa chuỗi sau đó, bạn có thể sử dụng một trong các chức năng sau:

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

Để sử dụng một trong các chức năng này trên myDummy$country:

 myDummy$country <- trim(myDummy$country)

Để 'hiển thị' khoảng trắng bạn có thể sử dụng:

 paste(myDummy$country)

sẽ cho bạn thấy các chuỗi được bao quanh bởi dấu ngoặc kép (") làm cho các khoảng trắng dễ dàng phát hiện hơn.


7
Như hadley đã chỉ ra regex này "^ \\ s + | \\ s + $" sẽ xác định khoảng trắng hàng đầu và dấu. vì vậy x <- gsub ("^ \\ s + | \\ s + $", "", x) nhiều hàm đọc của R có tùy chọn này: dải.white = FALSE
Jay

50
Xem thêm str_trimtrong stringrgói.
Cotton Richie

1
Thêm một cho "Chức năng Trim hiện được lưu trữ để sử dụng trong tương lai" - cảm ơn!
Chris Beeley

4
Thật không may, dải.white = TRUE chỉ hoạt động trên các chuỗi không được trích dẫn.
Rodrigo

2
Có một cách dễ dàng hơn nhiều để cắt khoảng trắng trong R 3.2.0. Xem câu trả lời tiếp theo!
Alex

519

Kể từ R 3.2.0, một chức năng mới đã được giới thiệu để loại bỏ các khoảng trắng hàng đầu / dấu vết:

trimws()

Xem: http://stat.ethz.ch/R-manual/R-patched/l Library / base / html / tômws.html


2
Nó phụ thuộc vào định nghĩa của một câu trả lời tốt nhất. Câu trả lời này rất hay khi biết (+1) nhưng trong một bài kiểm tra nhanh, nó không nhanh như một số lựa chọn thay thế ngoài kia.
A5C1D2H2I1M1N2O1R2T1

dường như không hoạt động đối với các chuỗi nhiều dòng, mặc dù \nnằm trong lớp nhân vật được bảo hiểm. trimws("SELECT\n blah\n FROM foo;")vẫn chứa dòng mới.
Jubble

6
@Jubble Đó là hành vi dự kiến. Trong chuỗi bạn chuyển đến trimws không có khoảng trắng ở đầu hoặc cuối. Nếu bạn muốn xóa các khoảng trắng hàng đầu và dấu cuối khỏi mỗi dòng trong chuỗi, trước tiên bạn sẽ phải tách nó ra. Như thế này: trimws (strsplit ("CHỌN \ n blah \ n TỪ foo;", "\ n") [[1]])
wligtenberg

1
Mặc dù chức năng tích hợp sẵn cho các phiên bản R gần đây, nhưng nó 'chỉ' thực hiện một biểu thức kiểu PERL dưới mui xe. Tôi có thể đã mong đợi một số mã C tùy chỉnh nhanh để làm điều này. Có lẽ trimwsregex là đủ nhanh. stringr::str_trim(dựa trên stringi) cũng thú vị ở chỗ nó sử dụng một thư viện chuỗi quốc tế hóa hoàn toàn độc lập. Bạn sẽ nghĩ khoảng trắng sẽ miễn nhiễm với các vấn đề với quốc tế hóa, nhưng tôi tự hỏi. Tôi chưa bao giờ thấy một so sánh kết quả của bản gốc so với stringr/ stringihoặc bất kỳ điểm chuẩn nào.
Jack Wasey

Vì một số lý do, tôi không thể tìm ra, trimws()đã không xóa các khoảng trắng hàng đầu của mình, trong khi Bryan trim.strings()bên dưới (chỉ có 1 phiếu bầu, của tôi!) Đã làm ...
PatrickT

89

Để thao tác khoảng trắng, sử dụng str_trim () trong gói stringr. Gói có hướng dẫn sử dụng ngày 15 tháng 2 năm 2013 và đang ở CRAN. Hàm này cũng có thể xử lý các vectơ chuỗi.

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

(tín dụng cho người bình luận: R. Cotton)


2
Giải pháp này đã loại bỏ một số khoảng trắng đột biến trimws()không thể xóa.
Richard Telford

1
@RichardTelford bạn có thể cung cấp một ví dụ? Bởi vì đó có thể được coi là một lỗi trong trimws.
wligtenberg

IMO đây là giải pháp tốt nhất. Không có nhiều mã và hiệu suất cao
Peter

Cảm ơn các yêu cầu (chuỗi) tài liệu hoặc ví dụ của họ không có dòng mã yêu cầu này!
pgee70

23

Một chức năng đơn giản để loại bỏ khoảng trắng hàng đầu và dấu:

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

Sử dụng:

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

11

ad1) Để xem khoảng trắng, bạn có thể gọi trực tiếp print.data.framebằng các đối số đã sửa đổi:

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"

Xem thêm ?print.data.framecho các tùy chọn khác.


9

Sử dụng grep hoặc grepl để tìm các quan sát với khoảng trắng và phụ để loại bỏ chúng.

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
Hoặc, ngắn gọn hơn một chút,"^\\s+|\\s+$"
hadley

4
Chỉ muốn chỉ ra rằng, người ta sẽ phải sử dụng gsubthay vì sử dụng subregrec của hadley. Với subnó sẽ loại bỏ khoảng trắng theo sau chỉ khi không có khoảng trắng hàng đầu ...
f3lix

Không biết bạn có thể sử dụng \ s, v.v với perl = FALSE. Các tài liệu nói rằng cú pháp POSIX được sử dụng trong trường hợp đó, nhưng cú pháp được chấp nhận thực sự là một siêu ký tự được xác định bởi thư viện TRE regex laurikari.net/tre/documentation/regex-syntax
Jyotirmoy Bhattacharya

5

Tôi muốn thêm câu trả lời dưới dạng nhận xét cho người dùng56 nhưng chưa thể viết như một câu trả lời độc lập. Việc xóa các khoảng trống hàng đầu và dấu có thể đạt được thông qua hàm trim () khỏi gói gdata:

require(gdata)
example(trim)

Ví dụ sử dụng:

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

5

Một vấn đề liên quan khác xảy ra nếu bạn có nhiều khoảng trống giữa các đầu vào:

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

Sau đó, bạn có thể dễ dàng phân tách chuỗi này thành các mã thông báo "thực" bằng cách sử dụng biểu thức chính quy cho splitđối số:

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

Lưu ý rằng nếu có một kết quả khớp ở đầu chuỗi (không trống), phần tử đầu tiên của đầu ra là '""', nhưng nếu có một kết quả khớp ở cuối chuỗi, thì đầu ra giống như với trận đấu bị loại bỏ.


5

Một tùy chọn khác là sử dụng stri_trimhàm từ stringigói mặc định để loại bỏ khoảng trắng hàng đầu và dấu:

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

Để chỉ loại bỏ khoảng trắng hàng đầu, sử dụng stri_trim_left. Để chỉ xóa khoảng trắng dấu, sử dụng stri_trim_right. Khi bạn muốn xóa các ký tự đầu hoặc cuối khác, bạn phải chỉ định rằng vớipattern = .

Xem thêm ?stri_trimđể biết thêm.


2

Tôi đã tạo một trim.strings ()hàm để cắt khoảng trắng hàng đầu và / hoặc dấu như:

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

Để minh họa,

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

Phương pháp tốt nhất là trimws ()

Mã sau sẽ áp dụng chức năng này cho toàn bộ khung dữ liệu

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


hoặc df[] <- lapply(df, trimws)để gọn hơn. Nhưng trong cả hai trường hợp, nó sẽ ép các cột thành ký tự. df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)để được an toàn.
Moody_Mudskipper

1

Tôi đã thử cắt (). Hoạt động tốt với khoảng trắng cũng như '\ n'. x = '\ n Harden, J. \ n'

cắt (x)


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

Sau này, bạn sẽ cần buộc R không nhận ra "Áo" là cấp độ. Hãy giả vờ rằng bạn cũng có "Hoa Kỳ" và "Tây Ban Nha" theo cấp độ:

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

Một chút ít đáng sợ hơn so với phản hồi được bình chọn cao nhất, nhưng nó vẫn hoạt động.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.