2016-01-13 17 views
5

Ich habe diese df:Count Zeichen eines Abschnitts eines Strings

dput(df) 
structure(list(URLs = c("http://bursesvp.ro//portal/user/_/Banco_Votorantim_Cartoes/0-7f2f5cb67f1-22918b.html", 
"http://46.165.216.78/.CartoesVotorantim/Usuarios/Cadastro/BV6102891782/", 
"http://www.chalcedonyhotel.com/images/promoc/premiado.tam.fidelidade/", 
"http://bmbt.ro/portal/a3/_Votorantim_/VotorantimCartoes2016/0-7f2f5cb67f1-22928b.html", 
"http://voeazul.nl/azul/")), .Names = "URLs", row.names = c(NA, 
-5L), class = "data.frame") 

Es unterschiedliche URLs beschreibt und ich versuche, die Anzahl der Zeichen des Namens Host zu zählen, ob das ein tatsächlicher Name (http://hostname.com/....) Oder eine IP (http://000.000.000.000/...). Wenn es sich jedoch um einen tatsächlichen Namen handelt, möchte ich nur den nchar zwischen www. und .com. Wenn es eine IP ist, dann alle ihre Nummern und "dazwischen" Punkte.

erwartetes Ergebnis für die obigen Beispieldaten:

exp_outcome 
1   8 
2   13 
3   15 
4   4 
5   7 

Ich hat versucht, etwas mit strsplit zu tun, kann aber nicht überall.

Antwort

7

Ein weiterer, vielleicht direkterer Weg mit einer anderen Regex:

nchar(sub("^http://(www\\.)?(([a-z]+)|([0-9.]+))(\\.[a-z]+)?/+.+$", "\\2", x$df)) 
#[1] 8 13 15 4 7 

Erklärung:

  • ^http://: sucht nach "http: //" nach Beginn der Zeichenfolge
  • (www\\.)?: sucht nach "www.", Null oder einmal (so ist dies optional)
  • (([a-z]+)|([0-9.]+)): das Muster, das erfasst wird: entweder Kleinbuchstaben eine oder mehrere Male oder Ziffern und Punkte
  • (\\.[a-z]+)?: sucht nach "." gefolgt von einem oder mehreren Kleinbuchstaben, null oder einmal (so wieder optional)
  • /+.+$: sucht nach „/“ gefolgt von irgendetwas, ein oder mehrere Male bis zum Ende der Zeichenfolge

NB:

sub("^http://(www\\.)?(([a-z]+)|([0-9.]+))(\\.[a-z]+)?/+.+$", "\\2", x$df) 
# [1] "bursesvp"  "46.165.216.78" "chalcedonyhotel" "bmbt"   "voeazul" 
+0

Das ist großartig, und ich ziehe es meiner eigenen Lösung vor - aber ich muss fragen: warum schreibe '/ {2}' anstelle von '/ {2}' oder sogar '//', und Warum schreibe 'w {3}' statt 'www'? Es ist länger und weniger lesbar. Anstelle von '(www) *' sollten Sie '(www)?' Verwenden, weil wir "null oder eins", nicht "null oder mehr" (und dasselbe später) wollen. Und noch eine letzte Sache: Domain-Namen können mehr als nur Buchstaben enthalten, sie können auch Ziffern und Bindestriche und viele andere Dinge enthalten. Eine Charakterklasse wird es also nicht schneiden, du musst wahrscheinlich alles außer '.' und'/'hier akzeptieren. –

+0

@KonradRudolph danke, [/] es ist zu vermeiden, zu entkommen/und [//] wird nicht funktionieren. w {3} es ist nur weil ich nicht www (persönliche wahl ...) wiederholen wollte. Danke für die Bemerkung zu "?", Es wäre in der Tat angemessener. Ich bin es nicht gewohnt? abgesehen von Umsicht. – Cath

+0

Tatsächlich, [Wikipedia sagt] (https://en.wikipedia.org/wiki/Domain_name), dass nur Zeichen und Zahlen in Domain-Namen zulässig sind, und Bindestriche, wenn sie von ersterem umgeben sind (so dass dies eine Fehlerbehebung für mein Anliegen vereinfacht über). Und es gibt keine Notwendigkeit zu entkommen '/'. Nur '\\' muss geflüchtet werden. –

5

Hier ist, wie es zu tun (vorausgesetzt, Ihr data.framex genannt wird):

domains = sub('^(http://)([^/]+)(.*)$', '\\2', x$df) 
# This will fail for IP addresses … 
hostname = sub('^(www\\.)?([^.]+)(\\..+)?$', '\\2', domains) 
# … which we treat separately here: 
is_ip = grepl('^(\\d{1,3}\\.){3}\\d{1,3}$', domains) 
hostname[is_ip] = domains[is_ip] 

exp_outcome$domain_length = nchar(hostname) 

Auf einer Seite beachten, ich konvertiert Ihre ursprüngliche data.frame auf Zeichenketten - es einfach keinen Sinn macht, einen factor zu verwenden für URLs.

0

nach 5 Monaten mit URLs im allgemeinen zu tun, fand ich die folgenden Pakete, die Leben ein bisschen leichter (Regex von anderen Antworten zur Verfügung gestellt von der Art und Weise große arbeiten),

library(urltools) 
library(iptools) 

df$Hostname <- domain(df$URLs) 
#However, TLDs and 'www' need to go so I used suffix_extract()$domain from `iptools` 
df$Hostname <- ifelse(is.na(suffix_extract(df$Hostname)$domain), df$Hostname, 
              suffix_extract(df$Hostname)$domain) 

#which gives: 
# URLs               Hostname 
#1 http://bursesvp.ro//portal/user/_/...       bursesvp 
#2 http://46.165.216.78/.CartoesVotorantim/Usuarios/...   46.165.216.78 
#3 http://www.chalcedonyhotel.com/images/promoc/     chalcedonyhotel 
#4 http://bmbt.ro/portal/a3/_Votorantim_/...      bmbt 
#5 http://voeazul.nl/azul/          voeazul 

#then simply, 

nchar(df$Hostname) 
#[1] 8 13 15 4 7 
Verwandte Themen