Bir desene göre bir alt dizeyi ayıklayın


136

Dize listesi olduğunu varsayalım:

string = c("G1:E001", "G2:E002", "G3:E003")

Şimdi sadece iki nokta üst üste ":" den sonraki parçaları içeren bir dizi vektörü elde etmeyi umuyorum, yani substring = c(E001,E002,E003).

R'de bunu yapmanın uygun bir yolu var mı? Kullanıyor substrmusunuz?

Yanıtlar:


239

İşte birkaç yol:

1) alt

sub(".*:", "", string)
## [1] "E001" "E002" "E003"

2) strsplit

sapply(strsplit(string, ":"), "[", 2)
## [1] "E001" "E002" "E003"

3) read.table

read.table(text = string, sep = ":", as.is = TRUE)$V2
## [1] "E001" "E002" "E003"

4) alt dize

Bu, ikinci kısmın her zaman 4. karakterden başladığını varsayar (sorudaki örnekte durum budur):

substring(string, 4)
## [1] "E001" "E002" "E003"

4a) alt dize / normal ifade

İki nokta üst üste her zaman bilinen bir konumda olmasaydı, arayarak (4) 'ü değiştirebilirdik:

substring(string, regexpr(":", string) + 1)

5) strapplyc

strapplyc parantez içindeki kısmı döndürür:

library(gsubfn)
strapplyc(string, ":(.*)", simplify = TRUE)
## [1] "E001" "E002" "E003"

6) read.dcf

Bu, yalnızca iki nokta üst üste işaretinden önceki alt dizeler benzersizse çalışır (sorudaki örnekte bunlar). Ayrıca ayırıcının iki nokta üst üste olmasını gerektirir (soruda bu vardır). Farklı bir ayırıcı kullanıldıysa, subonu önce iki nokta üst üste ile değiştirebilirdik. Örneğin, ayırıcı o _zamanstring <- sub("_", ":", string)

c(read.dcf(textConnection(string)))
## [1] "E001" "E002" "E003"

7) ayrı

7a) Kullanarak tidyr::separateiki sütunlu bir veri çerçevesi oluşturuyoruz, biri kolondan önceki kısım ve diğeri sonraki kısım için ve sonra ikincisini çıkarıyoruz.

library(dplyr)
library(tidyr)
library(purrr)

DF <- data.frame(string)
DF %>% 
  separate(string, into = c("pre", "post")) %>% 
  pull("post")
## [1] "E001" "E002" "E003"

7b) Alternatif olarak separate, yalnızca postsütunu ve ardından unlistve unnameelde edilen veri çerçevesini oluşturmak için kullanılabilir :

library(dplyr)
library(tidyr)

DF %>% 
  separate(string, into = c(NA, "post")) %>% 
  unlist %>%
  unname
## [1] "E001" "E002" "E003"

8) trimws Biz kullanabilirsiniz trimwsnokta üst üste kırpmak için yeniden kullanmak daha sonra sol kapalı süs kelime karakterlerine ve.

trimws(trimws(string, "left", "\\w"), "left", ":")
## [1] "E001" "E002" "E003"

Not

Girişin stringşu şekilde olduğu varsayılır:

string <- c("G1:E001", "G2:E002", "G3:E003")

Erimiş bir tabloda _ayırıcı olarak bulunan ve @Grothendieck cevabına göre önek ve sonek için iki ayrı değişken oluşturan bir değişkenim vardı : prefix <- sub("_.*", "", variable)ve suffix <- sub(".*_", "", variable)
swihart

Bu harika cevabın mikro karşılaştırmasını görmek güzel olurdu!
patL

25

Örneğin gsubveya kullanaraksub

    gsub('.*:(.*)','\\1',string)
    [1] "E001" "E002" "E003"

bunların ne olduğunu açıklar mısın? * (* tam olarak orada mı? Bunu sadece biraz farklı bir ortamda yeniden oluşturmakta zorlanıyorum ...
Peter Pan

1
@PeterPan Bu, iki noktadan sonra görünen karakter grubunu yakalar ve döndürür. Eşleşecek dizeler daha karmaşıksa ve R tabanında kalmak istiyorsanız, bu iyi çalışır.
Clark Fitzgerald


9

Partiye geç, ancak gelecek nesil için, stringr paketi (popüler "tidyverse" paket paketinin bir parçası) artık string işleme için uyumlu imzalara sahip işlevler sağlıyor:

string <- c("G1:E001", "G2:E002", "G3:E003")
# match string to keep
stringr::str_extract(string = string, pattern = "E[0-9]+")
# [1] "E001" "E002" "E003"

# replace leading string with ""
stringr::str_remove(string = string, pattern = "^.*:")
# [1] "E001" "E002" "E003"

2
Bu, kolondan sonraki her şey yerine, E ile başlayan ilk sayıyı bulmak değil mi?
Mark Neal

6

Bu şunları yapmalıdır:

gsub("[A-Z][1-9]:", "", string)

verir

[1] "E001" "E002" "E003"

3

Eğer kullanıyorsanız, data.tableo zaman tstrsplit()doğal bir seçimdir:

tstrsplit(string, ":")[[2]]
[1] "E001" "E002" "E003"

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.