我现在已经不教用这个包了,因为R核心包stats的reshape函数足够方便,还更灵活。用R核心的包还有一个好处就是不会什么时候没有人维护就不兼容了。 这是之前教程里的内容,这里单独放一个页面,留个纪念吧。
reshape包里我主要用的是cast和melt两个函数,如果没有安装reshape这个包,则预先安装一下。
options(stringsAsFactors=FALSE) options(scipen=20) # 发现学号显示为科学计数法了,可以通过这个设置来改变。 library(reshape) dat <- read.delim("ftp://ftp.biolab.wang/data/成绩.tsv", header=TRUE, sep='\t', encoding="GBK") str(dat) ## 'data.frame': 830 obs. of 7 variables: ## $ 学号 : num 71024000001 71024000001 71024000001 71024000001 71024000002 ... ## $ 姓名 : chr "梁全" "梁全" "梁全" "梁全" ... ## $ 班级 : chr "3班" "3班" "3班" "3班" ... ## $ 课程编号: int 1006001 1006017 1006036 1006002 1006001 1006017 1006036 1006002 1006001 1006017 ... ## $ 课程名称: chr "体育" "解剖学" "物理学" "英语" ... ## $ 学分 : num 2 4.5 4 4 2 4.5 4 4 2 4.5 ... ## $ 成绩 : int 76 81 61 61 77 83 75 67 80 72 ... head(dat) ## 学号 姓名 班级 课程编号 课程名称 学分 成绩 ## 1 71024000001 梁全 3班 1006001 体育 2.0 76 ## 2 71024000001 梁全 3班 1006017 解剖学 4.5 81 ## 3 71024000001 梁全 3班 1006036 物理学 4.0 61 ## 4 71024000001 梁全 3班 1006002 英语 4.0 61 ## 5 71024000002 李海丽 3班 1006001 体育 2.0 77 ## 6 71024000002 李海丽 3班 1006017 解剖学 4.5 83
我们可以把每个人的所有成绩放一行展示,使用cast函数,将长数据转换为宽数据:
Dat <- cast(dat, 学号+姓名+班级~课程名称, value="成绩") ## Aggregation requires fun.aggregate: length used as default head(Dat) ## 学号 姓名 班级 基础化学 解剖学 体育 物理学 细胞生物学 英语 ## 1 71024000001 梁全 3班 0 1 1 1 0 1 ## 2 71024000002 李海丽 3班 0 1 1 1 0 1 ## 3 71024000003 李昕婧 3班 0 1 1 1 0 1 ## 4 71024000004 廖娇 3班 0 1 1 1 0 1 ## 5 71024000005 陈雅文 3班 0 1 1 1 0 1 ## 6 71024000006 李清玲 3班 0 1 1 1 0 1 Dat <- cast(dat, 学号+姓名+班级~课程名称, value="成绩", fun.aggregate=max, fill=NA) head(Dat) ## 学号 姓名 班级 基础化学 解剖学 体育 物理学 细胞生物学 英语 ## 1 71024000001 梁全 3班 NA 81 76 61 NA 61 ## 2 71024000002 李海丽 3班 NA 83 77 75 NA 67 ## 3 71024000003 李昕婧 3班 NA 72 80 68 NA 81 ## 4 71024000004 廖娇 3班 NA 80 82 78 NA 83 ## 5 71024000005 陈雅文 3班 NA 77 79 73 NA 76 ## 6 71024000006 李清玲 3班 NA 81 86 81 NA 70 str(Dat) ## List of 9 ## $ 学号 : num [1:161] 71024000001 71024000002 71024000003 71024000004 71024000005 ... ## $ 姓名 : chr [1:161] "梁全" "李海丽" "李昕婧" "廖娇" ... ## $ 班级 : chr [1:161] "3班" "3班" "3班" "3班" ... ## $ 基础化学 : int [1:161] NA NA NA NA NA NA NA NA NA NA ... ## $ 解剖学 : int [1:161] 81 83 72 80 77 81 68 81 84 82 ... ## $ 体育 : int [1:161] 76 77 80 82 79 86 84 82 84 87 ... ## $ 物理学 : int [1:161] 61 75 68 78 73 81 68 79 79 76 ... ## $ 细胞生物学: int [1:161] NA NA NA NA NA NA NA NA NA NA ... ## $ 英语 : int [1:161] 61 67 81 83 76 70 81 70 83 83 ... ## - attr(*, "row.names")= int [1:161] 1 2 3 4 5 6 7 8 9 10 ... ## - attr(*, "idvars")= chr [1:3] "学号" "姓名" "班级" ## - attr(*, "rdimnames")=List of 2 ## ..$ :'data.frame': 161 obs. of 3 variables: ## .. ..$ 学号: num [1:161] 71024000001 71024000002 71024000003 71024000004 71024000005 ... ## .. ..$ 姓名: chr [1:161] "梁全" "李海丽" "李昕婧" "廖娇" ... ## .. ..$ 班级: chr [1:161] "3班" "3班" "3班" "3班" ... ## ..$ :'data.frame': 6 obs. of 1 variable: ## .. ..$ 课程名称: chr [1:6] "基础化学" "解剖学" "体育" "物理学" ... class(Dat) ## [1] "cast_df" "data.frame" Dat <- data.frame(Dat) str(Dat) ## 'data.frame': 161 obs. of 9 variables: ## $ 学号 : num 71024000001 71024000002 71024000003 71024000004 71024000005 ... ## $ 姓名 : chr "梁全" "李海丽" "李昕婧" "廖娇" ... ## $ 班级 : chr "3班" "3班" "3班" "3班" ... ## $ 基础化学 : int NA NA NA NA NA NA NA NA NA NA ... ## $ 解剖学 : int 81 83 72 80 77 81 68 81 84 82 ... ## $ 体育 : int 76 77 80 82 79 86 84 82 84 87 ... ## $ 物理学 : int 61 75 68 78 73 81 68 79 79 76 ... ## $ 细胞生物学: int NA NA NA NA NA NA NA NA NA NA ... ## $ 英语 : int 61 67 81 83 76 70 81 70 83 83 ...
可看到这里返回了一个信息,有的同学成绩对应多个值,这时候就需要指定汇总(Aggregation)函数,比如这里使用max,最最大值也就是最高分。可以看到,cast得到的对象并不是一个单纯的data.frame, 还是cast_df, 可以将它转化为data.frame。
设置了options(scipen=20),如果发现学号显示为科学计数法了,可以通过这个设置来改变。
met则是cast的逆向过程,将宽数据变形为长数据
DAT <- melt(Dat, id=1:3) str(DAT) ## 'data.frame': 966 obs. of 5 variables: ## $ 学号 : num 71024000001 71024000002 71024000003 71024000004 71024000005 ... ## $ 姓名 : chr "梁全" "李海丽" "李昕婧" "廖娇" ... ## $ 班级 : chr "3班" "3班" "3班" "3班" ... ## $ variable: Factor w/ 6 levels "基础化学","解剖学",..: 1 1 1 1 1 1 1 1 1 1 ... ## $ value : int NA NA NA NA NA NA NA NA NA NA ... names(DAT)[4:5] <- c("科目", "成绩") str(melt(Dat)) ## Using 姓名, 班级 as id variables ## 'data.frame': 1127 obs. of 4 variables: ## $ 姓名 : chr "梁全" "李海丽" "李昕婧" "廖娇" ... ## $ 班级 : chr "3班" "3班" "3班" "3班" ... ## $ variable: Factor w/ 7 levels "学号","基础化学",..: 1 1 1 1 1 1 1 1 1 1 ... ## $ value : num 71024000001 71024000002 71024000003 71024000004 71024000005 ...
melt之后变量一列的表头默认为variable,而数值一列默认为value,可以把列名改成所需要的。如果不设置id列,那么R会去把字符型的列当作id,这种行为是我们无法控制的,因此,设置好id是非常重要的。也可以通过id.vars和measure.vars来更具体地指定。
另外Reshape的作者Hadley Wickham还有一个包叫reshape2,Reshape2现在已经退休了。在某些方面比Reshape高效,但在我们一般的使用中用Reshape就足够了。
本网页已被访问162次。