Voici les données dont je dispose,
> dataf v11_a v11_b v12_a v12_b v13_a v13_b 1 24 31 0 0 31 64 2 31 28 0 0 18 58
Je veux diviser chaque colonne (de la v11 à la v99) en deux colonnes. J'utilise substr
pour le diviser comme ceci pour la première colonne,
v11 %>% separate(v11, into = c('v11_a', 'v11_b'), sep = 4) Error in UseMethod("separate_") : no applicable method for 'separate_' applied to an object of class "character"
Ça a l'air bien sauf la colonne X_data
. Je ne veux pas l'avoir dans la sortie. Une meilleure façon de faire ça?
tidyr :: separ
ne sera pas applicable car mes données sont de type caractère?
transform(v11, v11_a = substr(v11, 1, 4), v11_b = substr(v11, 5, 8)) X_data v11_a v11_b 1 00240031 0024 0031 2 00310028 0031 0028
Deuxièmement, comment puis-je répéter le processus pour les colonnes suivantes (par exemple v11 à v99)?
Idéalement, après la division, puis la conversion en type numérique, mes données finales devraient ressembler à ceci,
v11 <- c("00240031", "00310028") v12 <- c("00000000", "00000000") v13 <- c("00310064", "00180058") data <- data.frame(v11, v12, v13) data <- lapply(data, as.character) testdata <- as.data.frame(data, stringsAsFactors = F) testdata[testdata == '0'] <- '000000000' testdata
Commentaire:
La rapidité avec laquelle vous trouvez des solutions étonnantes est incroyable. Merci à tous.
3 Réponses :
En base R
, cela peut être fait en faisant une boucle dans les colonnes, en remplaçant les 0 entre non-zéro par un délimiteur ,
, lu dans un data.frame ( read.table
), et cbind
la liste
des ensembles de données
testdata %>% summarise_all(funs(list(read.table(text =sub("^(....)", "\\1 ", .), header = FALSE)))) %>% unnest
Cela peut être également fait avec tidyverse
en d'abord rassembler
au format 'long', puis faire l'ion séparé
, et enfin spread code > retournez-le au format 'large'
library(tidyverse) gather(testdata) %>% separate(value, into = c('a', 'b'), sep=4, convert = TRUE) %>% gather(key1, val, a:b) %>% unite(key, key, key1, sep="_") %>% group_by(key) %>% mutate(ind = row_number()) %>% spread(key, val) %>% select(-ind) # A tibble: 2 x 6 # v11_a v11_b v12_a v12_b v13_a v13_b # <int> <int> <int> <int> <int> <int> #1 24 31 0 0 31 64 #2 31 28 0 0 18 58
Ou une autre option consiste à utiliser summary_all
avec read.table code >
lst1 <- lapply(testdata, function(x) { x1 <- read.table(text = sub("(?<=[1-9])0+", ",", x, perl = TRUE), header = FALSE, sep=",", col.names = c('a', 'b'), fill = TRUE) replace(x1, is.na(x1), 0)}) do.call(cbind, lst1) # v11.a v11.b v12.a v12.b v13.a v13.b #1 24 31 0 0 31 64 #2 31 28 0 0 18 58
Merci beaucoup. Fonctionne comme un charme. Vous êtes, comme d'habitude, l'un des meilleurs sauveteurs ici. Avez-vous des lectures recommandées pour moi afin que je puisse les faire moi-même?
@ome. Heureux de savoir que cela fonctionne. Je suggérerais de pratiquer au moins une heure par jour en plus de la lecture. Je pense que sur YouTube, vous pouvez obtenir beaucoup de vidéos gratuites, mais la pratique est importante
Voici une idée utilisant le très pratique pour de telles opérations library(splitstackshape)
,
library(splitstackshape) cSplit(setDT(testdata)[, lapply(.SD, function(i) gsub("(.{4})", "\\1 ", i))], names(testdata), sep = ' ') # v11_1 v11_2 v12_1 v12_2 v13_1 v13_2 #1: 24 31 0 0 31 64 #2: 31 28 0 0 18 58
On dirait un paquet très pratique.
Certains jouent dans data.table
et réutilisent votre logique substr ()
existante:
library(data.table) setDT(testdata) cols <- paste0("v", 11:13) new_cols <- paste0(rep(cols, 2), rep(c("a", "b"), each = length(cols))) extra <- function(x) substr(x, 1, 4) extrb <- function(x) substr(x, 5, 8) testdata[, (new_cols) := c(lapply(.SD, extra), lapply(.SD, extrb)), .SDcols = cols] > testdata v11 v12 v13 v11a v12a v13a v11b v12b v13b 1: 00240031 00000000 00310064 0024 0000 0031 0031 0000 0064 2: 00310028 00000000 00180058 0031 0000 0018 0028 0000 0058
J'aime la facilité de débogage de votre code. Une idée comment avoir une sortie sans les trois premières colonnes?
Vous pouvez les supprimer avec testdata [! Cols, with = FALSE]
.
Cela peut être utile: stackoverflow.com/questions / 26660571 /…