マルチステージサンプリング方式からプライマリ、セカンダリ、およびアルティメットサンプリングユニットを識別する数値ID変数を持つデータフレームがあります。元のID変数を3つの新しい変数に分割して、異なるサンプリングユニットを個別に識別したいと思います。
例:
>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で文字列を分割するための関数がいくつかあることは知っていますが、数値に対して同じ機能を見つけることができませんでした。
ありがとうございました、
ファン
まだanother代わりに、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
ここでの利点の1つは、結果の列名を便利な方法で設定でき、列が文字であることを確認できるため、存在する可能性のある先行ゼロがすべて保持されることです。
たとえば、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
これはうまくいくはずです:
_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])
_
何年も前にいくつかのきちんとした答えが出されていますが、outer
関数を使用して私が役立つと思う解決策は言及されていません。この検索エンジンの時代に、他の人が便利に使えるようにここに置いておきます。
私は少し単純な問題に直面しました:6桁の数値の列を、各桁を表す6列に変換します。これは、outer
、整数除算(%/%
)およびモジュロ(%%
)。
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
それらは数値なので、必要な数字を抽出するためにいくつかの計算を行う必要があります。基数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)
出来上がり!結果を整数として解釈すると、最上位の桁が抽出されました。これは、他のすべての桁の重みが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
何らかの理由で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
たくさんの答えがあるので、何かを考え出す必要があるように感じました:)
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