countcol is the name of the column containing the countsSee more in [http://www.cookbook-r.com/Manipulating_data/Recoding_data/]
Xử lý dữ liệu với data set mtcars
require(tidyr)## Loading required package: tidyr
require(plyr)## Loading required package: plyr
require(ggplot2)## Loading required package: ggplot2
require(reshape2)## Loading required package: reshape2
df <- mtcars
head(df)## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
str(df)## 'data.frame': 32 obs. of 11 variables:
## $ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
## $ cyl : num 6 6 4 6 8 6 8 4 4 6 ...
## $ disp: num 160 160 108 258 360 ...
## $ hp : num 110 110 93 110 175 105 245 62 95 123 ...
## $ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
## $ wt : num 2.62 2.88 2.32 3.21 3.44 ...
## $ qsec: num 16.5 17 18.6 19.4 17 ...
## $ vs : num 0 0 1 1 0 1 0 1 1 1 ...
## $ am : num 1 1 1 0 0 0 0 0 0 0 ...
## $ gear: num 4 4 4 3 3 3 3 4 4 4 ...
## $ carb: num 4 4 1 1 2 1 4 2 2 4 ...
Data set mtcars được lấy từ tạp chí Motor Trend US trong năm 1974, bao gồm dữ liệu về tiêu thụ nhiên liệu và 10 đặc điểm thiết kế của 32 loại xe ô tô. Data set có 11 biến số: mpg: tiêu thụ nhiên liệu (dặm/gallon), cyl: số xy lanh, disp, hp: công suất, drat: tỷ số xoắn…
Trong data set am là kiểu hộp số được mã hóa với 2 giá trị 0 (số tự động), 1(số điều khiển bằng tay). Chúng ta sẽ mã hóa lại biến số am thành dạng factor với tên lần lượt là automatic và manual và gán cho một biến số mới có tên là trans. ## 1.1. Mã hóa dữ liệu dạng thứ bậc
df$trans <- factor(df$am, levels=c(0, 1), labels=c("Automatic", "Manual"))package(plyr).Chú ý: hàm relevel() chỉ làm việc với biến dạng factor.
require(plyr)
df$am <- as.factor(df$am)
df$trans2 <- revalue(df$am, c("0"="Automatic", "1"="Manual"))
df$trans3 <- mapvalues(df$am, from=c("0", "1"), to = c("Automatic", "Manual"))
levels(df$trans3)## [1] "Automatic" "Manual"
df$trans4[df$am=="0"] <- "Automatic"
df$trans4[df$am=="1"] <- "Manual"match() functionoldvalues <- c("0", "1")
newvalues <- factor(c("Automatic", "Manual"))
df$trans <- newvalues[match(df$am, oldvalues)]Giả sử chúng ta muốn mã hóa dữ liệu công suất của 32 dòng ô tô thành 3 nhóm: cao (H), trung bình (M), thấp (L) và gán các giá trị này vào một biến số mới có tên power.
df$power[df$hp < 96.5] <- "L"
df$power[df$hp >180] <- "H"
df$power[96.5 <= df$hp & df$hp <=180] <- "M"cutdf$power <- cut(df$hp,
breaks=c(-Inf, 96.5, 180, Inf),
labels=c("L", "M", "H"))
# By default, the ranges are open on the left and closed on the right as (96.5, 180]df <- mtcars
df$vs <- factor(df$vs)
# We can also specify the order of levels when we create the variables or transforming it
df$vs <- factor(mtcars$vs, levels=c("0", "1"))
df$vs1 <- factor(mtcars$vs, levels=c("1", "0"))
df$vs2 <- as.character(mtcars$vs)
str(df)## 'data.frame': 32 obs. of 13 variables:
## $ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
## $ cyl : num 6 6 4 6 8 6 8 4 4 6 ...
## $ disp: num 160 160 108 258 360 ...
## $ hp : num 110 110 93 110 175 105 245 62 95 123 ...
## $ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
## $ wt : num 2.62 2.88 2.32 3.21 3.44 ...
## $ qsec: num 16.5 17 18.6 19.4 17 ...
## $ vs : Factor w/ 2 levels "0","1": 1 1 2 2 1 2 1 2 2 2 ...
## $ am : num 1 1 1 0 0 0 0 0 0 0 ...
## $ gear: num 4 4 4 3 3 3 3 4 4 4 ...
## $ carb: num 4 4 1 1 2 1 4 2 2 4 ...
## $ vs1 : Factor w/ 2 levels "1","0": 2 2 1 1 2 1 2 1 1 1 ...
## $ vs2 : chr "0" "0" "1" "1" ...
df$vs2 <- as.numeric(df$vs2)
df$vs2 <- as.factor(as.character(mtcars$vs))Đổi dữ liệu từ dạng factor sang dạng character rất dễ dàng bằng lệnh as.character().
df$vs1 <- as.character(df$vs)Biến đổi từ dạng factor sang dạng numeric phức tạp hơn. Nếu chỉ sử dụng as.numeric() thì chỉ có số mã hóa cho factor được chuyển sang dạng số. Do vậy, trước hết ta biến đổi biến factor sang dạng character sau đó mới chuyển về sạng số.
df$vs2 <- as.numeric(as.character(df$vs2))
str(df)## 'data.frame': 32 obs. of 13 variables:
## $ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
## $ cyl : num 6 6 4 6 8 6 8 4 4 6 ...
## $ disp: num 160 160 108 258 360 ...
## $ hp : num 110 110 93 110 175 105 245 62 95 123 ...
## $ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
## $ wt : num 2.62 2.88 2.32 3.21 3.44 ...
## $ qsec: num 16.5 17 18.6 19.4 17 ...
## $ vs : Factor w/ 2 levels "0","1": 1 1 2 2 1 2 1 2 2 2 ...
## $ am : num 1 1 1 0 0 0 0 0 0 0 ...
## $ gear: num 4 4 4 3 3 3 3 4 4 4 ...
## $ carb: num 4 4 1 1 2 1 4 2 2 4 ...
## $ vs1 : chr "0" "0" "1" "1" ...
## $ vs2 : num 0 0 1 1 0 1 0 1 1 1 ...
sort() functionv <- sample(100:110)
sort(v, decreasing=TRUE)## [1] 110 109 108 107 106 105 104 103 102 101 100
arrange() function in package plyrdf <- data.frame(id = 1:4,
weight = c(20, 27, 24, 22),
size = c("small", "large", "medium", "large"))
df## id weight size
## 1 1 20 small
## 2 2 27 large
## 3 3 24 medium
## 4 4 22 large
require(plyr)
# Sắp xếp theo weight
arrange(df, weight)## id weight size
## 1 1 20 small
## 2 4 22 large
## 3 3 24 medium
## 4 2 27 large
# Sắp xếp theo size sau đó theo weight
arrange(df, size, weight, decreasing= TRUE)## id weight size
## 1 1 20 small
## 2 3 24 medium
## 3 2 27 large
## 4 4 22 large
Mặc định của arrange là sắp xếp theo thứ tự tăng dần, nếu muốn cột nào đó được sắp xếp theo tứ tự giảm dần có thể thêm desc vào trước tên cột đó.
arrange(df, size, desc(weight))## id weight size
## 1 2 27 large
## 2 4 22 large
## 3 3 24 medium
## 4 1 20 small
revalue() hoặc mapvalues() từ package plyr*str(df)## 'data.frame': 4 obs. of 3 variables:
## $ id : int 1 2 3 4
## $ weight: num 20 27 24 22
## $ size : Factor w/ 3 levels "large","medium",..: 3 1 2 1
levels(df$size)## [1] "large" "medium" "small"
df$size <- revalue(df$size, c("large"="L", "small"="S", "medium"="M"))
df$size <- mapvalues(df$size, from=c("S","M","L"), to=c("Small", "Medium", "Large"))factor() hoặc droplevels()Việc này được thực hiện khi một biến factor có một hay nhiều bậc thực tế không tồn tại trong data xảy ra khi nhập dữ liệu hoặc loại bỏ bớt một số dòng trong data.
x <- factor(c("alpha", "beta", "alpha"), levels=c("alpha", "beta", "gama"))
x## [1] alpha beta alpha
## Levels: alpha beta gama
x <- factor(x)
x## [1] alpha beta alpha
## Levels: alpha beta
Sau khi nhập dữ liệu, data frame có thể chứa đồng thời nhiều biến dạng factor cùng với các biến số dạng khác, trong trường hợp này chúng ta có thể tính lại bậc của tất cả các biến factor bằng cách sử dụng droplevels() function.
# Create a data frame with extra level
df <- data.frame(x=factor(c("alpha", "beta", "alpha"), levels=c("alpha", "beta", "gamma")),
y=c(5,8,2),
z=factor(c("red", "green", "green"), levels=c("red", "green", "blue")))
str(df)## 'data.frame': 3 obs. of 3 variables:
## $ x: Factor w/ 3 levels "alpha","beta",..: 1 2 1
## $ y: num 5 8 2
## $ z: Factor w/ 3 levels "red","green",..: 1 2 2
df <- droplevels(df)
str(df)## 'data.frame': 3 obs. of 3 variables:
## $ x: Factor w/ 2 levels "alpha","beta": 1 2 1
## $ y: num 5 8 2
## $ z: Factor w/ 2 levels "red","green": 1 2 2
Có 2 loại biến factor trong R: biến factor dạng thứ bậc (ordered) và dạng không thứ bậc(unordered). Cách thứ nhất để thay đổi thứ tự các level là sử dụng hàm factor() lên factor và chỉ ra thứ tự một cách trực tiếp. Cách thứ 2 là sử dụng hàm ordered().
str(df)## 'data.frame': 3 obs. of 3 variables:
## $ x: Factor w/ 2 levels "alpha","beta": 1 2 1
## $ y: num 5 8 2
## $ z: Factor w/ 2 levels "red","green": 1 2 2
df$x <- factor(df$x, levels=c("beta", "alpha"))
str(df)## 'data.frame': 3 obs. of 3 variables:
## $ x: Factor w/ 2 levels "beta","alpha": 2 1 2
## $ y: num 5 8 2
## $ z: Factor w/ 2 levels "red","green": 1 2 2
Một cách khác để thay đổi thứ bậc là sử dụng hàm relevel(), khi đó một bậc cụ thể sẽ được đưa lên đầu, các bậc còn lại được lùi một bậc. Chú ý cách này không áo dụng với các biến factor dạng thứ bậc.
str(df)## 'data.frame': 3 obs. of 3 variables:
## $ x: Factor w/ 2 levels "beta","alpha": 2 1 2
## $ y: num 5 8 2
## $ z: Factor w/ 2 levels "red","green": 1 2 2
x <- factor(df$x)
x## [1] alpha beta alpha
## Levels: beta alpha
x <- relevel(x, "alpha")
# câu lệnh sau đây sẽ cho ra lỗi
x <- ordered(df$x)
#x
#x <- relevel(x,"alpha")df <- data.frame(alpha=1:3, beta=4:6, gamma=7:9)
df## alpha beta gamma
## 1 1 4 7
## 2 2 5 8
## 3 3 6 9
require(plyr)
df <- rename(df, c("alpha"="A", "beta"="B"))***NOTE: sử dụng chỉ số kiểu ma trận để lấy một phần data frame cho các kết quả khác nhau khi chúng ta chỉ lấy một cột trong data frame. Trong trường hợp này kết quả trả về là một vector. Để tránh điều này chúng ta nên sử dụng chỉ số kiểu danh sách (list) hoặc sử dụng drop=FALSE.
merge()stories2 <- read.table(header=TRUE, text='
id title
1 lions
2 tigers
3 bears
')
data <- data <- read.table(header=TRUE, text='
subject storyid rating
1 1 6.7
1 2 4.5
1 3 3.7
2 2 3.3
2 3 4.1
2 1 5.2
')
merge(x=stories2, y=data, by.x="id", by.y="storyid")## id title subject rating
## 1 1 lions 1 6.7
## 2 1 lions 2 5.2
## 3 2 tigers 1 4.5
## 4 2 tigers 2 3.3
## 5 3 bears 1 3.7
## 6 3 bears 2 4.1
Như vậy lệnh merge sẽ kiểm tra xem giá trị nào của cột id trong stories2 giống giá trị trong cột storyid trong data để nối 2 data frame lại với nhau. Trong ví dụ trên, merge tìm được giá trị 1 trong cột id của stories2, sau đó merge tìm các giá trị 1 trong cột storyid của data và add thêm giá trị của các dòng tương tứng vào data frame mới, loại bỏ cột storyid.
Ngoài ra lệnh merge cũng cho phép nối nhiều cột trong 2 data frame với nhau.
animals <- read.table(header=T, text='
size type name
small cat lynx
big cat tiger
small dog chihuahua
big dog "great dane"
cat dog dog
')
observations <- read.table(header=T, text='
number size type
1 big cat
2 small dog
3 small dog
4 big dog
')
merge(animals, observations, c("size", "type"))## size type name number
## 1 big cat tiger 1
## 2 big dog great dane 4
## 3 small dog chihuahua 2
## 4 small dog chihuahua 3
*NOTE: merge() tìm giá trị trong cột size và type tương ứng trong animals, sau đó tìm xem có các giá trị đó trong size và type của observations hay không. Nếu không có, ví dụ: small cat không có trong observations, vì vậy trong data frame mới không có giá trị này. Ngược lại với giá trị small dog, merge() tìm thấy 2 dòng tương ứng trong data nên nó trả về kết quả 2 dòng.
Có 2 phương pháp chính để chuyển đổi giữa dữ liệu dạng bảng ngắn và bảng dài.
- gather() và spread() trong package tidyr - melt() và dcast() trong package reshape2
Tạo 2 data frame có dạng bảng rộng (nhiều cột) và bảng dài (ít cột)
df_wide <- read.table(header=TRUE, text='
subject sex control cond1 cond2
1 M 7.9 12.3 10.7
2 F 6.3 10.6 11.1
3 F 9.5 13.1 13.8
4 M 11.5 13.4 12.9
')
df_wide$subject <- factor(df_wide$subject)
df_long <- read.table(header=TRUE, text='
subject sex condition measurement
1 M control 7.9
1 M cond1 12.3
1 M cond2 10.7
2 F control 6.3
2 F cond1 10.6
2 F cond2 11.1
3 F control 9.5
3 F cond1 13.1
3 F cond2 13.8
4 M control 11.5
4 M cond1 13.4
4 M cond2 12.9
')
df_long$subject <- factor(df_long$subject)tidyrRộng \(\rightarrow\) dài sử dụng gather()
data_long <- gather(df_wide, condition, measurement, control:cond2)Dài \(\rightarrow\) rộng sử dụng spread()
spread(df_long, condition, measurement)## subject sex cond1 cond2 control
## 1 1 M 12.3 10.7 7.9
## 2 2 F 10.6 11.1 6.3
## 3 3 F 13.1 13.8 9.5
## 4 4 M 13.4 12.9 11.5
reshape2Rộng \(\rightarrow\) dài sử dụng melt()
melt(df_wide,
id.vars=c("subject", "sex"),
variable.name = "Treatment",
measure.vars = c("control","cond1", "cond2"),
value.name = "Measurement")## subject sex Treatment Measurement
## 1 1 M control 7.9
## 2 2 F control 6.3
## 3 3 F control 9.5
## 4 4 M control 11.5
## 5 1 M cond1 12.3
## 6 2 F cond1 10.6
## 7 3 F cond1 13.1
## 8 4 M cond1 13.4
## 9 1 M cond2 10.7
## 10 2 F cond2 11.1
## 11 3 F cond2 13.8
## 12 4 M cond2 12.9
Dài \(\rightarrow\) rộng sử dụng dcast()
dcast(df_long, subject+sex ~ condition,
value.var="measurement")## subject sex cond1 cond2 control
## 1 1 M 12.3 10.7 7.9
## 2 2 F 10.6 11.1 6.3
## 3 3 F 13.1 13.8 9.5
## 4 4 M 13.4 12.9 11.5
cases là một data frame mà mỗi dòng thể hiện một trường hợpctable: là một bảng ngẫu nhiên, mỗi biến nằm ởcounts: một data frame của các số đếm, mỗi dòng là một sự kết hợp của nhiều biến và tần số suất hiện của sự kết hợp đó.
Ví dụ:
cases <- data.frame(
Sex=c("M", "M", "F", "F", "F"),
Color=c("brown", "blue", "brown", "brown", "brown")
)
cases## Sex Color
## 1 M brown
## 2 M blue
## 3 F brown
## 4 F brown
## 5 F brown
# Contigency table
ctable <- table(cases)
# table with count of each combination
counts <- data.frame(
Sex=c("F", "M", "F", "M"),
Color=c("blue", "blue", "brown", "brown"),
Freq=c(0, 1, 3, 1)
)
counts## Sex Color Freq
## 1 F blue 0
## 2 M blue 1
## 3 F brown 3
## 4 M brown 1
countdf <- as.data.frame(table(cases))
countdf## Sex Color Freq
## 1 F blue 0
## 2 M blue 1
## 3 F brown 3
## 4 M brown 1
countcol is the name of the column containing the countscountsToCases <- function(x, countcol = “Freq”) { # Get the row indices to pull from x idx <- rep.int(seq_len(nrow(x)), x[[countcol]])
# Drop count column
x[[countcol]] <- NULL
# Get the rows from x
x[idx, ]
} ## Contigency table to Cases ctable <- table(cases) ctable cases <- countsToCases(as.data.frame(ctable)) ````
rep(1, 4)## [1] 1 1 1 1
# Lặp lại các giá trị theo các số khác nhau. Ví dụ lặp lại 1 2 lần 2 4 lần 3 6 lần
unlist(mapply(rep, 1:3, seq(2,6, by=2)))## [1] 1 1 2 2 2 2 3 3 3 3 3 3