Подтвердить что ты не робот

Как разбить число на цифры в R

У меня есть кадр данных с переменной числового идентификатора, который идентифицирует первичные, вторичные и конечные единицы выборки из многоступенчатой ​​схемы выборки. Я хочу разбить исходную идентификационную переменную на три новые переменные, идентифицируя разные единицы выборки отдельно:

Пример:

>df[1:2,]
ID Var        var1     var2      var3     var4         var5  
501901          9    SP.1          1        W         12.10    
501901          9    SP.1          2        W         17.68  

Что я хочу:

>df[1:2,]
ID1    ID2     ID3   var1   var2  var3     var4    var5  
5      01      901    9    SP.1    1        W     12.10    
5      01      901    9    SP.1    2        W     17.68  

Я знаю, что в R есть некоторые функции, чтобы разделить строки символов, но я не мог найти одинаковые возможности для чисел.

Спасибо,

Хуан

4b9b3361

Ответ 1

Еще одна альтернатива - перечитать первый столбец с помощью read.fwf и указать ширину:

cbind(read.fwf(file = textConnection(as.character(df[, 1])), 
               widths = c(1, 2, 3), colClasses = "character", 
               col.names = c("ID1", "ID2", "ID3")), 
      df[-1])
#   ID1 ID2 ID3 var1 var2 var3 var4  var5
# 1   5  01 901    9 SP.1    1    W 12.10
# 2   5  01 901    9 SP.1    2    W 17.68

Одно из преимуществ заключается в том, что вы можете установить результирующие имена столбцов удобным образом и убедиться, что столбцы являются символами, тем самым сохраняя любые ведущие нули, которые могут присутствовать.

Ответ 2

Можно использовать, например, substring:

df <- data.frame(ID = c(501901, 501902))

splitted <- t(sapply(df$ID, function(x) substring(x, first=c(1,2,4), last=c(1,3,6))))
cbind(df, splitted)
#      ID 1  2   3
#1 501901 5 01 901
#2 501902 5 01 902

Ответ 3

Поскольку они являются числами, вам нужно будет сделать некоторую математику, чтобы извлечь нужные цифры. Число, представленное в radix-10, может быть записано как:

d0*10^0 + d1*10^1 + d2*10^2 ... etc. where d0..dn are the digits of the number.

Таким образом, чтобы извлечь наиболее значимую цифру из 6-значного числа, которое математически представлено как:

number = d5*10^5 + d4*10^4 + d3*10^3 + d2*10^2 + d1*10^1 + d0*10^0

Как вы можете видеть, деление этого числа на 10 ^ 5 даст вам:

number / 10^5 = d5*10^0 + d4*10^(-1) + d3*10^(-2) + d2*10^(-3) + d1*10^(-4) + d0*10^(-5)

Voila! Теперь вы извлекли наиболее значимую цифру, если интерпретируете результат как целое число, потому что все остальные цифры теперь имеют вес менее 0 и, следовательно, меньше 1. Вы можете делать подобные вещи для извлечения других цифр. Для цифр в наименее значимом положении вы можете выполнять операцию по модулю вместо деления.

Примеры:

501901 / 10^5 = 5 // first digit
501901 % 10^5 = 1 // last digit
(501901 / 10^4) % 10^1 = 0 // second digit
(501901 / 10^2) % 10^2 = 19 // third and fourth digit

Ответ 4

Это должно работать:

df <- cbind(do.call(rbind, strsplit(gsub('(.)(..)(...)', '\\1 \\2 \\3', paste(df[,1])),' ')), df[,-1]) # You need that paste() there because gsub() works only with text.

Или с substr()

df <- cbind(ID1=substr(df[, 1],1,1), ID2=substr(df[, 1],2,3), ID3=substr(df[, 1],4,6), df[, -1])

Ответ 5

Несколько полезных ответов были сделаны несколько лет назад, но решение, которое я считаю полезным, используя функцию outer, не упоминалось. В этом возрасте поисковых систем я поставил его здесь, чтобы другие могли найти его удобным.

Мне пришлось столкнуться с несколько более простой проблемой: превратить столбец из 6-значных чисел в 6 столбцов, представляющих каждую цифру. Это можно решить, используя комбинацию outer, целочисленное деление (%/%) и modulo (%%).

 DF <- data.frame("ID" = runif(3)*10^6, "a" = sample(letters, 3,T))
 DF <- cbind(DF, "ID" = outer(DF$ID, 10^c(5:0), function(a, b) a %/% b %% 10))
 DF
#       ID a ID.1 ID.2 ID.3 ID.4 ID.5 ID.6
# 1 814895 z    8    1    4    8    9    5
# 2 417209 q    4    1    7    2    0    9
# 3 545797 c    5    4    5    7    9    7

Заданный здесь вопрос немного сложнее, требуя разных значений как для деления целого числа, так и по модулю.

 DF <- data.frame("ID" = runif(3)*10^6, "a" = sample(letters, 3,T))
 DF <- cbind(DF, "ID" = outer(DF$ID, c(1:3), function(a,b) a %/% 10^c(5,3,0)[b] %% 10^b))
 DF
#      ID a ID.1 ID.2 ID.3
# 1 809372 q    8    9  372
# 2 954790 g    9   54  789
# 3 166970 l    1   66  969

Ответ 6

Если вы не хотите конвертировать в character по какой-либо причине, следуйте одним из способов достижения желаемого

DF <- data.frame(ID = c(501901, 501902), var1 = c("a", "b"), var2 = c("c", "d"))

result <- t(sapply(DF$ID, function(y) {
    c(y%/%1e+05, (y - y%/%1e+05 * 1e+05)%/%1000, y - y%/%1000 * 1000)
}))


DF <- cbind(result, DF[, -1])

names(DF)[1:3] <- c("ID1", "ID2", "ID3")

DF
##   ID1 ID2 ID3 var1 var2
## 1   5   1 901    a    c
## 2   5   1 902    b    d

Ответ 7

С таким количеством ответов мне показалось, что мне нужно что-то придумать:)

library(qdap)
x <- colSplit(dat$ID_Var, col.sep="")
data.frame(ID1=x[, 1], ID2=paste2(x[, 2:3], sep=""), 
    ID3=paste2(x[, 4:6],sep=""), dat[, -1])

##   ID1 ID2 ID3 var1 var2 var3 var4  var5
## 1   5  01 901    9 SP.1    1    W 12.10
## 2   5  01 901    9 SP.1    2    W 17.68