2015年9月3日 星期四

如何將資料為每列表示變數資料轉換為行資料

Problem:

如何將資料為每列表示變數,每行表示一筆記錄資料轉換為每列表示記錄,每行表示變數之資料框(data.frame)物件,此功能類似 Excel \ 複製 \ 右鍵 \ 貼上選項 \ 轉置.

感謝 R user - Hsieh 提供此問題

Analysis:

# 匯入資料 read.table 函數中,可以先設定 stringsAsFactors=FALSE, 如此所有資料可先保留字串資料型態
> myData <- read.table("rowdata.csv", sep=",", stringsAsFactors=FALSE)
> myData
     V1   V2   V3    V4    V5   V6
1  編號    1    2     3     4    5
2  型式  AAA  AAA   BBB   BBB  CCC
3 測量1   10   20    30    40   50
4 測量2  100  200   300   400  500
5 測量3 1000 2000  3000  4000 5000
6  結果   OK   OK ERROR ERROR   OK
> str(myData)
'data.frame': 6 obs. of  6 variables:
 $ V1: chr  "編號" "型式" "測量1" "測量2" ...
 $ V2: chr  "1" "AAA" "10" "100" ...
 $ V3: chr  "2" "AAA" "20" "200" ...
 $ V4: chr  "3" "BBB" "30" "300" ...
 $ V5: chr  "4" "BBB" "40" "400" ...
 $ V6: chr  "5" "CCC" "50" "500" ...


# 資料轉換(t函數),結果是矩陣 matrix,此結果與data.frame之需求不符合
> t(myData)
   [,1]   [,2]   [,3]    [,4]    [,5]    [,6]   
V1 "編號" "型式" "測量1" "測量2" "測量3" "結果" 
V2 "1"    "AAA"  "10"    "100"   "1000"  "OK"   
V3 "2"    "AAA"  "20"    "200"   "2000"  "OK"   
V4 "3"    "BBB"  "30"    "300"   "3000"  "ERROR"
V5 "4"    "BBB"  "40"    "400"   "4000"  "ERROR"
V6 "5"    "CCC"  "50"    "500"   "5000"  "OK"   
> class(t(myData))
[1] "matrix"


# 將資料轉換之矩陣再轉為資料框 data.frame,此結果應該是可以使用
> myData.df <- as.data.frame(t(myData), stringsAsFactors=FALSE)
> str(myData.df)
'data.frame': 6 obs. of  6 variables:
 $ V1: chr  "編號" "1" "2" "3" ...
 $ V2: chr  "型式" "AAA" "AAA" "BBB" ...
 $ V3: chr  "測量1" "10" "20" "30" ...
 $ V4: chr  "測量2" "100" "200" "300" ...
 $ V5: chr  "測量3" "1000" "2000" "3000" ...
 $ V6: chr  "結果" "OK" "OK" "ERROR" ...
> myData.df
     V1   V2    V3    V4    V5    V6
V1 編號 型式 測量1 測量2 測量3  結果
V2    1  AAA    10   100  1000    OK
V3    2  AAA    20   200  2000    OK
V4    3  BBB    30   300  3000 ERROR
V5    4  BBB    40   400  4000 ERROR
V6    5  CCC    50   500  5000    OK


# 欄位名稱調整
> names(myData.df) <- myData.df[1,]
>

# 考慮刪除列名稱
> row.names(myData.df) <- NULL
>

# 刪除第1列多餘資料
> (myData.df <- myData.df[-1,])
   編號 型式 測量1 測量2 測量3  結果
V2    1  AAA    10   100  1000    OK
V3    2  AAA    20   200  2000    OK
V4    3  BBB    30   300  3000 ERROR
V5    4  BBB    40   400  4000 ERROR
V6    5  CCC    50   500  5000    OK
> str(myData.df)
'data.frame': 5 obs. of  6 variables:
 $ 編號 : chr  "1" "2" "3" "4" ...
 $ 型式 : chr  "AAA" "AAA" "BBB" "BBB" ...
 $ 測量1: chr  "10" "20" "30" "40" ...
 $ 測量2: chr  "100" "200" "300" "400" ...
 $ 測量3: chr  "1000" "2000" "3000" "4000" ...
 $ 結果 : chr  "OK" "OK" "ERROR" "ERROR" ...


# 目前資料轉換正常,唯數值字料尚須轉換
# 選取1欄,將字串轉換為數值資料
> myData.df$測量1
[1] "10" "20" "30" "40" "50"
> as.numeric(myData.df$測量1)
[1] 10 20 30 40 50


> # 如果資料欄位較多,似乎須考量非一行一行轉換!
> # 判斷將所有欄資料並轉換為數值資料,保留無法轉換為數值之字串資料
> for (i in 1:dim(myData.df)[2]) {
+   if (all(!is.na(as.numeric(myData.df[,i])))) {
+     myData.df[,i] <- as.numeric(myData.df[,i])
+   }
+ }
Warning messages:
1: NAs introduced by coercion 
2: NAs introduced by coercion 


> # 第1,3-5欄已轉換為數值資料
> str(myData.df)
'data.frame': 5 obs. of  6 variables:
 $ 編號 : num  1 2 3 4 5
 $ 型式 : chr  "AAA" "AAA" "BBB" "BBB" ...
 $ 測量1: num  10 20 30 40 50
 $ 測量2: num  100 200 300 400 500
 $ 測量3: num  1000 2000 3000 4000 5000
 $ 結果 : chr  "OK" "OK" "ERROR" "ERROR" ...
> myData.df
   編號 型式 測量1 測量2 測量3  結果
V2    1  AAA    10   100  1000    OK
V3    2  AAA    20   200  2000    OK
V4    3  BBB    30   300  3000 ERROR
V5    4  BBB    40   400  4000 ERROR
V6    5  CCC    50   500  5000    OK
> # end


R code:

####################################
# title    : 列轉換為行之數值資料
# date     : 2015.9.3
# author   : Ming-Chang Lee
# email    : alan9956@gmail.com
# RWEPA    : http://rwepa.blogspot.tw/
# encoding : UTF-8
####################################
# 匯入資料
myData <- read.table("rowdata.csv", sep=",", stringsAsFactors=FALSE)
myData
str(myData)

# 資料轉換(t函數),結果是矩陣 matrix
t(myData)
class(t(myData))

# 將資料轉換之矩陣再轉為資料框 data frame
myData.df <- as.data.frame(t(myData), stringsAsFactors=FALSE)
str(myData.df)
myData.df

# 欄位名稱調整
names(myData.df) <- myData.df[1,]

# 考慮刪除列名稱
row.names(myData.df) <- NULL

# 刪除第1列多餘資料
(myData.df <- myData.df[-1,])
str(myData.df)

# 目前資料轉換正常,唯數值字料尚須轉換
# 選取1欄,將字串轉換為數值資料
myData.df$測量1
as.numeric(myData.df$測量1)

# 如果資料欄位較多,似乎須考量非一行一行轉換!
# 判斷將所有欄資料並轉換為數值資料,保留無法轉換為數值之字串資料
for (i in 1:dim(myData.df)[2]) {
  if (all(!is.na(as.numeric(myData.df[,i])))) {
    myData.df[,i] <- as.numeric(myData.df[,i])
  }
}

# 第1,3-5欄已轉換為數值資料
str(myData.df)
myData.df

# end