Re: [問題] 資料轉換

作者: celestialgod (天)   2015-11-15 14:16:38
關於使用迴圈,我有一點想法可以參考看看
最下方補上不用for-loop的方法
# data generation
set.seed(300)
N = 100
df = data.frame(x = sample(1:100, N, TRUE), y = runif(N),
z = sample(0:1, N, TRUE, prob = c(0.4, 0.6)))
# 計算重複的長度,已取得我需要preallocate多大的矩陣
zLength = rle(df$z)$lengths
# zLength:
# [1] 4 3 1 1 2 1 2 1 1 2 2 1 4 3 1 1 2 1 1 2 1 3 1 2
# [25] 1 3 1 3 1 2 2 2 1 2 1 2 2 5 4 2 10 3 2 1 1 2 2 2
# 超過五的部分都要多加一行
outRow = length(zLength) + zLength[zLength > 5] %/% 5 +
as.numeric(zLength[(zLength > 5)] %% 5 > 0) - sum(zLength > 5)
# outRow:
# [1] 49 (只有一個超過5,只需要多一行)
# create output matrix and preallocate
outMat = matrix(NA, outRow, 5)
# 上一個值
lastValue = 1 - df$z[1]
j = 0 # row編號
k = 0 # col編號
rowNamesVec = vector('numeric', outRow) # 存rownames
for (i in 1:nrow(df))
{
if (df$z[i] != lastValue) # 如果跟上一個值不相同就跑這塊
{
j = j + 1 # 移到下一個row
k = 1 # col回到1 (新的row)
outMat[j, k] = df$x[i] # assign進去output的matrix
lastValue = df$z[i] # 把這次的z存起來做下一次的判斷
rowNamesVec[j] = df$z[i] # 存下這次的z以assign rownames
}
else # 如果跟上一個值相同就跑這塊
{
k = k + 1 # 移到下一個column
if (k > 5) # 如果k超過五就移到下一個row 並且存進rownames
{
j = j + 1
k = 1
rowNamesVec[j] = df$z[i]
}
outMat[j, k] = df$x[i] # assign進去output的matrix
}
}
rownames(outMat) = rowNamesVec # 賦予rownames
outMat結果:
[,1] [,2] [,3] [,4] [,5]
0 92 77 81 74 NA
1 69 2 76 NA NA
0 50 NA NA NA NA
1 47 NA NA NA NA
0 91 95 NA NA NA
1 32 NA NA NA NA
0 80 59 NA NA NA
1 66 NA NA NA NA
0 99 NA NA NA NA
1 89 67 NA NA NA
0 64 51 NA NA NA
1 99 NA NA NA NA
0 50 47 7 10 NA
1 3 53 90 NA NA
0 70 NA NA NA NA
1 23 NA NA NA NA
0 52 72 NA NA NA
1 93 NA NA NA NA
0 39 NA NA NA NA
1 10 46 NA NA NA
0 40 NA NA NA NA
1 76 62 78 NA NA
0 37 NA NA NA NA
1 1 74 NA NA NA
0 88 NA NA NA NA
1 38 87 56 NA NA
0 35 NA NA NA NA
1 13 75 38 NA NA
0 80 NA NA NA NA
1 60 100 NA NA NA
0 91 59 NA NA NA
1 47 89 NA NA NA
0 86 NA NA NA NA
1 5 37 NA NA NA
0 63 NA NA NA NA
1 65 30 NA NA NA
0 22 60 NA NA NA
1 44 52 79 78 64
0 86 25 7 51 NA
1 31 42 NA NA NA
0 92 13 68 82 19
0 21 95 42 24 66
1 67 91 44 NA NA
0 92 31 NA NA NA
1 84 NA NA NA NA
0 52 NA NA NA NA
1 75 40 NA NA NA
0 68 17 NA NA NA
1 60 20 NA NA NA
## no for loop
continueLength = rle(df$z)$lengths
splitGroup = rep(1:length(continueLength), continueLength)
outMat = lapply(split(df, splitGroup), function(subdf){
if (length(subdf$x) <= 5)
c(subdf$x, rep(NA, 5 - length(subdf$x)))
else
{
numRows = length(subdf$x) %/% 5 + as.numeric(length(subdf$x) %% 5 > 0)
NAnum = 5 - length(subdf$x)%%5
matrix(c(subdf$x,rep(NA,NAnum)), numRows, 5, byrow = TRUE)
}
})
outMat = do.call(rbind, outMat)
rownames(outMat)[nchar(rownames(outMat)) != 0] = rle(df$z)$values
※ 引述《Rose9305 (台產零零柒)》之銘言:
: [問題類型]:
: 程式諮詢(我想用R 做某件事情,但是我不知道要怎麼用R 寫出來)
: [軟體熟悉度]:
: 新手(沒寫過程式,R 是我的第一次)
: [問題敘述]:
: 資料轉換
: 我有個資料csv檔,裡面內容大概如下 :
: x y z
: 55 0.2 1
: 44 0.6 1
: 78 0.7 0
: 46 0.8 0
: 98 0.9 1
: 47 0.4 1
: 46 0.5 1
: 想(限)用 ''for 迴圈''轉換成只取x,z並以z重排x,如下:
: 1 55 44
: 0 78 46
: 1 98 47 46
: 把 z=1 排成一列,一遇到 z=0 又排成一列,再讀到1又排成一列這樣下去
: 不知道要如何用for迴圈來把資料轉換成上述。
: 抱歉,再問下因實際DATA比較多,因此可以每列只列5個值然後換下一行嗎?
: 一樣用1,0排,
: 像是 1 55 44 67 78 46
: 1 47 48 99 78 16
: 0 48 49 77 66 55
: 1 76 78 79 88 99 這樣排列呢??

Links booklink

Contact Us: admin [ a t ] ucptt.com