J'ai un bloc de données que je veux diviser la chaîne de texte de la première colonne en deux colonnes, mais seulement après le deuxième espace blanc de la séquence. Voici un exemple:
test22 Ticker 1 Current SharePrice $6.57 MFM 2 Current NAV $7.11 MFM 3 Current Premium/Discount -7.59% MFM 4 52WkAvg SharePrice $6.55 MFM 5 52WkAvg NAV $7.21 MFM 6 52WkAvg Premium/Discount -9.19% MFM
Essentiellement, si le résultat final serait un bloc de données avec un total de trois colonnes et le champ prix /% étant sa propre colonne distincte. Merci!
3 Réponses :
Une option de la r consiste à créer un délimiteur ,
avec sub
puis utilisez read.csv
:
df1 <- structure(list(test22 = c("Current SharePrice $6.57", "Current NAV $7.11", "Current Premium/Discount -7.59%", "52WkAvg SharePrice $6.55", "52WkAvg NAV $7.21", "52WkAvg Premium/Discount -9.19%"), Ticker = c("MFM", "MFM", "MFM", "MFM", "MFM", "MFM")), class = "data.frame", row.names = c("1", "2", "3", "4", "5", "6"))
Ou en utilisant extraire de tidyr
library(tidyverse) df1 %>% extract(test22, into = c("V1", "V2"), "^(\\S+\\s+\\S+)\\s+(.*)") # V1 V2 Ticker #1 Current SharePrice $6.57 MFM #2 Current NAV $7.11 MFM #3 Current Premium/Discount -7.59% MFM #4 52WkAvg SharePrice $6.55 MFM #5 52WkAvg NAV $7.21 MFM #6 52WkAvg Premium/Discount -9.19% MFM
out <- cbind(read.csv(text = sub(" (\\S+)$", ",\\1", df1$test22), header = FALSE, stringsAsFactors = FALSE), df1[2]) out #. V1 V2 Ticker #1 Current SharePrice $6.57 MFM #2 Current NAV $7.11 MFM #3 Current Premium/Discount -7.59% MFM #4 52WkAvg SharePrice $6.55 MFM #5 52WkAvg NAV $7.21 MFM #6 52WkAvg Premium/Discount -9.19% MFM
Voici une option utilisant strsplit
gsub('.*\\s.*?\\s(.*)','\\1', df$test22, perl = TRUE) # [1] "$6.57" "$7.11" "-7.59%" "$6.55" "$7.21" "-9.19%" # or if factors # gsub('.*\\s.*?\\s(.*)','\\1', as.character(df$test22), perl = TRUE)
Ou utilisant gsub
data.frame(do.call(rbind, strsplit(df$test22, '\\s(?!.*\\s)', perl = TRUE)), Ticker=df$Ticker) # X1 X2 Ticker # 1 Current SharePrice $6.57 MFM # 2 Current NAV $7.11 MFM # 3 Current Premium/Discount -7.59% MFM # 4 52WkAvg SharePrice $6.55 MFM # 5 52WkAvg NAV $7.21 MFM # 6 52WkAvg Premium/Discount -9.19% MFM
L'avantage du second est qu'il considère vraiment le second caractère d'espacement (par opposition au dernier espacement).
J'obtiens l'erreur suivante avec ceci mais je l'applique à une grande trame de données: Erreur dans strsplit (df6 $ test22, "\\ s (?!. * \\ s)", perl = TRUE): non- argument de caractère
@ js80 Mayber parce que vous avez des facteurs. Essayez: as.character (df $ test22)
dans strsplit
au lieu de df $ test22
. Ou peut-être essayez l'option scond.
Voici une option utilisant dplyr
et stringr
:
library(dplyr) library(stringr) data <- tibble(test22 = c("Current SharePrice $6.57", "Current NAV $7.11", "Current Premium/Discount -7.59%", "52WkAvg SharePrice $6.55", "52WkAvg NAV $7.21", "52WkAvg Premium/Discount -9.19%"), Ticker = "MFM") data %>% mutate(category = str_replace(test22, "^(.+ .+) (.+)$", "\\1"), price_pc = str_replace(test22, "^(.+ .+) (.+)$", "\\2")) # A tibble: 6 x 4 test22 Ticker category price_pc <chr> <chr> <chr> <chr> 1 Current SharePrice $6.57 MFM Current SharePrice $6.57 2 Current NAV $7.11 MFM Current NAV $7.11 3 Current Premium/Discount -7.59% MFM Current Premium/Discount -7.59% 4 52WkAvg SharePrice $6.55 MFM 52WkAvg SharePrice $6.55 5 52WkAvg NAV $7.21 MFM 52WkAvg NAV $7.21 6 52WkAvg Premium/Discount -9.19% MFM 52WkAvg Premium/Discount -9.19%
EDIT: Explication de l'expression régulière utilisée
Ignorer les crochets pendant une seconde:
^ = début de la chaîne
. = tout caractère sauf une nouvelle ligne
+ = au moins un des caractères précédents (dans ce cas, tout caractère sauf une nouvelle ligne)
$ = fin de la chaîne
Donc "^ (. +. +) (. +) $"
recherche les chaînes qui commencent, ont des caractères, puis un espace, puis quelques caractères, puis un espace, puis quelques caractères supplémentaires, puis fin.
Les crochets sont ajoutés en tant que "groupes de capture", ce qui signifie que la requête "se souvient" de la partie de la chaîne qui est représenté par ces crochets et peut être extrait en se référant à l'ordre des crochets. Par conséquent, "\\ 1"
renvoie ce qui a été capturé par le premier crochet, et "\\ 2"
renvoie ce qui a été capturé par le second.
Une bonne ressource pour apprendre Regex est Regexr .
Pas de soucis @ js80. Un certain amour de réponse positive / choisie serait très apprécié.
Pouvez-vous expliquer la syntaxe: ^ (. +. +) (. +) $ "," \\ 1 "?
@ js80 a ajouté une explication ci-dessus, car elle était trop verbeuse pour un commentaire. En bref: c'est Regex.