Konvertieren Sie Zeichenfolgendaten in Datenrahmen


8

Ich bin neu bei R, Anregungen wären willkommen.

Dies sind die Daten:

coordinates <- "(-79.43591570873059, 43.68015339477487), (-79.43491506339724, 43.68036886994886), (-79.43394727223847, 43.680578504490335), (-79.43388162422195, 43.68058996121469), (-79.43281544978878, 43.680808044458765), (-79.4326971769691, 43.68079658822322)"

Ich möchte, dass dies wird:

Latitude           Longitude
-79.43591570873059 43.68015339477487
-79.43491506339724 43.68036886994886
-79.43394727223847 43.680578504490335
-79.43388162422195 43.68058996121469
-79.43281544978878 43.680808044458765
-79.4326971769691  43.68079658822322

Antworten:


3

Wir können str_extract_allvon verwendenstringr

library(stringr)

df <- data.frame(Latitude = str_extract_all(coordinates, "(?<=\\()-\\d+\\.\\d+")[[1]], 
      Longitude = str_extract_all(coordinates, "(?<=,\\s)\\d+\\.\\d+(?=\\))")[[1]])
df
#            Latitude          Longitude
#1 -79.43591570873059  43.68015339477487
#2 -79.43491506339724  43.68036886994886
#3 -79.43394727223847 43.680578504490335
#4 -79.43388162422195  43.68058996121469
#5 -79.43281544978878 43.680808044458765
#6  -79.4326971769691  43.68079658822322

LatitudeErfasst die negative Dezimalzahl vom Öffnen runder Klammern ( (), während Longitudesie von Komma ( ,) bis zum Schließen runder Klammern ( )) erfasst wird .

Oder ohne Regex Lookahead und dahinter und zusammen mit erfassen str_match_all

df <- data.frame(str_match_all(coordinates, 
                        "\\((-\\d+\\.\\d+),\\s(\\d+\\.\\d+)\\)")[[1]][, c(2, 3)])

Um Daten in ihre jeweiligen Typen zu konvertieren, können Sie verwenden type.convert

df <- type.convert(df)

Dies schafft Latitudeund Longitudeals Faktor Variablen, die Schwierigkeiten verursachen könnten.
Dcarlson

@dcarlson Die Antwort dafür wurde aktualisiert.
Ronak Shah

4

Sie können scanmit ein wenig verwenden gsub:

matrix(scan(text = gsub("[()]", "", coordinates), sep = ","), 
       ncol = 2, byrow = TRUE, dimnames = list(NULL, c("Lat", "Long")))
# Read 12 items
#            Lat     Long
# [1,] -79.43592 43.68015
# [2,] -79.43492 43.68037
# [3,] -79.43395 43.68058
# [4,] -79.43388 43.68059
# [5,] -79.43282 43.68081
# [6,] -79.43270 43.68080

Die Präzision ist immer noch da - nur in der Matrixanzeige abgeschnitten.

Zwei klare Vorteile:

  • Schnell.
  • Behandelt Mehrelement-Koordinatenvektoren (z. B. coordinates <- rep(coordinates, 10)als Eingabe).

Hier ist eine weitere Option:

library(data.table)
fread(gsub("[()]", "", gsub("), (", "\n", toString(coordinates), fixed = TRUE)), header = FALSE)

Das toString(coordinates)ist für Fälle, in denen length(coordinates) > 1. Sie können auch verwenden fread(text = gsub(...), ...)und überspringen toString. Ich bin mir der Vor- oder Nachteile beider Ansätze nicht sicher.


2

Hier ist eine Basis-R-Option:

coordinates <- "(-79.43591570873059, 43.68015339477487), (-79.43491506339724, 43.68036886994886), (-79.43394727223847, 43.680578504490335), (-79.43388162422195, 43.68058996121469), (-79.43281544978878, 43.680808044458765), (-79.4326971769691, 43.68079658822322)"
coordinates <- gsub("^\\(|\\)$", "", coordinates)
x <- strsplit(coordinates, "\\), \\(")[[1]]
df <- data.frame(lat=sub(",.*$", "", x), lng=sub("^.*, ", "", x), stringsAsFactors=FALSE)
df

Die Strategie hier besteht darin, zuerst die führenden nachfolgenden Klammern zu entfernen und dann die Zeichenfolge aufzuteilen \), \(, um mit jedem Breiten- / Längengradpaar einen einzelnen Zeichenvektor zu erzeugen. Schließlich generieren wir eine Datenrahmenausgabe.

                 lat                lng
1 -79.43591570873059  43.68015339477487
2 -79.43491506339724  43.68036886994886
3 -79.43394727223847 43.680578504490335
4 -79.43388162422195  43.68058996121469
5 -79.43281544978878 43.680808044458765
6  -79.4326971769691 43.68079658822322

Dies schafft latund lngals Faktor Variablen, die Schwierigkeiten verursachen könnten.
Dcarlson

1
@dcarlson Dann stringsAsFactors=FALSEbeim Erstellen des Datenrahmens verwenden .
Tim Biegeleisen

2

Eine weitere Basis-R-Version mit ein wenig Regex, die sich auf die Tatsache stützt, dass das Ersetzen der Interpunktion durch Leerzeilen bedeutet, dass sie beim Import übersprungen werden.

read.csv(text=gsub(")|(, |^)\\(", "\n", coordinates), col.names=c("lat","long"), header=FALSE)
#        lat     long
#1 -79.43592 43.68015
#2 -79.43492 43.68037
#3 -79.43395 43.68058
#4 -79.43388 43.68059
#5 -79.43282 43.68081
#6 -79.43270 43.68080

Vorteile:

  • Behandelt die Vektoreingabe ebenso wie die andere scanAntwort.
  • Konvertiert in korrekte numerische Typen in der Ausgabe

Nachteile:

  • Nicht super schnell

2

Wir können rm_roundvon verwendenqdapRegex

library(qdapRegex)
read.csv(text = rm_round(coordinates, extract = TRUE)[[1]], header = FALSE,
      col.names = c('lat', 'lng'))
#    lat      lng
#1 -79.43592 43.68015
#2 -79.43492 43.68037
#3 -79.43395 43.68058
#4 -79.43388 43.68059
#5 -79.43282 43.68081
#6 -79.43270 43.68080

Oder in Kombination mit tidyverse

library(tidyr)
library(dplyr)
rm_round(coordinates, extract = TRUE)[[1]] %>%
     tibble(col1 = .) %>%
     separate(col1, into = c('lat', 'lng'), sep= ",\\s*", convert = TRUE)
# A tibble: 6 x 2
#    lat   lng
#  <dbl> <dbl>
#1 -79.4  43.7
#2 -79.4  43.7
#3 -79.4  43.7
#4 -79.4  43.7
#5 -79.4  43.7
#6 -79.4  43.7
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.