Quantcast

袁伟时:中国的奴性和戾气从哪里来?

“芯片大学”虚晃一枪,人才断层问题不能跑步解决

两大中国首富双双被重挫-释放信号强烈

民间帝王赖小民和性感女星舒淇与许晴

女性最喜欢的五种性爱姿势(图)

Facebook Twitter

分享到微信朋友圈

点击图标下载本文截图到手机
即可分享到朋友圈。如何使用?

自由微信安卓APP发布,立即下载!
查看原文

将军笔记之数据管理

2017-07-27 ?? 生信菜鸟团 生信菜鸟团

我今天只想严肃



多达60%的数据分析时间都花在了实际分析前数据的准备上。

  1. 一个示例:

创建leadership数据库:

  1. 创建新变量:

变量名 <- 表达式

表达式中,x%%y 表示求余;x%/%y 表示整数除法;(那后面遇到的%*%是什么意思?%*%是向量和矩阵乘法)

sumx <- mydata$x1 + mydata$x2

meanx <- (mydata$x1 + mydata$x2)/2

上面两行,利用数据框中已有的数据增加了两个独立于数据库的变量

例子:在已有数据库中增加新的变量:

方法一:

方法二:

方法三:

第三种方法,transform()函数应该是把两个新的变量整合到了已有的数据框中形成了一个新的数据框。

  1. 变量的重编码:

一个有意思的逻辑运算符:isTRUE(x): 测试x是否为TRUE

将数据框leadership中的99岁的年龄变成NA:leadership$age[leadership$age == 99] <- NA #在这里,中括号似乎发挥了判断的作用:判断其中的表达式是否为TRUE,为TRUE则完成赋值;即:variable[condition] <- expression将仅在condition为TRUE时执行赋值;

创建agecat变量的方法:

leadership$agecat[leadership$age > 75] <- "Elder";

leadership$agecat[leadership$age >= 55 & leadership$age <= 75] <- "Middle Aged";

leadership$agecat[leadership$age < 55] <- "Young"

上述代码可以写得更紧凑:

leadership <- within(leadership,{

agecat <- NA

agecat[age > 75] <- "Elder"

agecat[age >= 55 & age <= 75] <- "Middle Aged"

agecat[age < 55] <- "Young" })

within()函数和with()函数类似,都使大括号内的语句针对数据库leadership进行。但within()允许修改数据框。上面的语句先创建agecat变量,并设为NA,之后再根据age变量的值对agecat变量进行赋值。

这样就把一个数字变量变成了字符变量。

  1. 变量的重命名:

可以使用fix(leadership)调用编辑器来改变变量名

或者使用reshape包中的rename()函数:rename(dataframe, c(oldname="newname",oldname = "newname",...)) #注意原名称不用加引号,但是新名称需要加引号。使用示例:

library(reshape)

leadership <- rename(leadership,c(manager="managerID",data="testDate")) #改完名字别忘了再赋值给原来的数据框。(注意是一个旧变量名=一个新变量名,一个一个地)

还可以通过names()函数来重命名变量:

names(leadership)[2] <- "testDate" #这个看起来好像是通过names(leadership)把leadership这个数据框中的变量名都取了出来,然后用[2]来指定第二个变量名,再通过赋值进行修改。

进阶用法:names(leadership)[6:10] <- c("item1","item2","item3","item4","item5")(后面这种方法用得最多)

  1. 缺失值:

函数is.na()检测缺失值是否存在(其实准确的说法是:检测哪些元素是缺失值,哪些不是)。例:

y <- c(1,2,3,NA)

is.na(y) #意思就是:y中各元素是缺失值吗?返回c(FALSE,FALSE,FALSE,TRUE)

is.na(leadership[,6:10]),检测数据框leadership所有行6-10列的元素是否为NA。

注意:缺失值被认为是不可比较的,两个缺失值之间也不可比较,所以不能用比较运算符来检测缺失值是否存在。myvar == NA的结果永远不会为TRUE。

排除缺失值:

因为含有缺失值的算数表达式和函数的计算结果也是缺失值,所以在计算式要把缺失值排除掉。

x <- c(1,2,NA,3)

y <- sum(x,na.rm=TRUE)

na.omit()函数可以删除所有含有缺失数据的行(整行删除啊...):newdata <- na.omit(leadership) #注意别忘了赋值给新的数据框

  1. 日期值

日期值通常以字符串形式输入,然后使用函数as.Date(x,"input_format")转化为数值形式存储的日期变量,x是字符型数据,input_format给出格式。

%d 两位数字表示的日期 31

%a 三字母缩写的星期 Mon

%A 非缩写的星期 Monday

%m 两位数字表示的月份 00-12

%b 缩写的月份 Jan

%B 非缩写的月份 January

%y 两位数的年份 17

%Y 四位数的年份 2017

日期默认的输入格式为yyyy-mm-dd: mydata <- as.Date(c("2017-06-22","2012-09-11")) #因为是默认写法,所以不用加input_format。注意这里可以用c()函数。

strDates <- c("01/05/1965","08/16/1975")

dates <- as.Date(strDates,"%m/%d/%Y") 注意input_format要加引号。注意format要和字符串对应,比如,这里应该有斜杠。

还可以这样:myformat <- "%m/%d/%y"; leadership$date <-as.Date(leadership$date,myformat) #变量的灵活运用,放哪都行。

Sys.Date()返回当天日期;date()返回当前的日期和时间(%a %b %d 时间 %Y)。Sys.Date()返回的是日期型数据,而date()返回的是字符数据。竟然有这等事...

这两个函数输出的数据可以使用format()函数来指定格式:format(x,format="output_format")。today <- Sys.Date(); format(today,format="%B %d %y"); format(today,format="%A")(函数名和里面的选项的名字都是format啊...)

R使用1970年1月1日以来的天数来储存日期,更早的表示为负数。

startdate <- as.Date("2014-10-01")

enddate <- as.Date("2017-06-30")

days <- enddate - startdate #返回:Time difference of 1003 days


还可以使用difftime()来计算时间间隔,并以星期、天、时分秒来表示:

today <- Sys.Date()

dob <- as.Date("1988-04-02")

difftime(today,dob,units="weeks") #使用units选项来指定单位

返回:Time difference of 1512.429 weeks

strDates <- as.character(dates) #将日期值转换为字符型


  1. 类型转换

向一个数值型向量中添加一个字符串会将此向量中的所有元素转换为字符型。

判断对象的数据类型和将其转换为另一种数据类型的函数:

is.numeric() as.numeric()

is.character() as.character()

is.vector() as.vector()

is.matrix() as.matrix()

is.data.frame() as.data.frame()(这两个一个是判断,一个是转换。如果新建的话,用data.frame())

is.factor() as.factor()

is.logical() as.logical()

就记住R中这些数据类型就行,然后is就是判断是不是,as就是转换成这种数据类型。上面既有数据类型,又有数据结构,注意区分。


  1. 数据排序

使用order()函数对一个数据框进行排序。在排序变量前加一个减号即可得到降序的排序结果:newdata <- leadership[order(leadership$age),] #对leadership这个数据框进行排序,根据age变量。注意后面的逗号。

上图中的例子按两个变量对数据框进行排序。

依据排序的变量前面加个负号,就会反过来排序了。

  1. 数据集的合并:

要横向合并数据集,使用merge()函数。两个数据框是通过一个或多个共有变量进行联接的(内连接。注意和MySQL中的概念很像)。例:total <- merge(dataframeA, dataframeB, by="ID") #注意使用by来指定通过该变量联结,连这个用法都和MySQL一样。 如果是根据多个变量进行联结,就指定多个变量:total <- merge(dataframeA, dataframeB, by=c("ID","Country")) #注意多个变量要用c()函数连接。好像只要涉及多个变量都要用c()函数连接。横向连接通常用于向数据框中添加变量。

如果直接合并,不指定公共索引的话,就是用cbind()函数:total <- cbind(A, B)。此时要求A和B必须行数相同。#cbind()中的c就是column,就是把列合并起来,所以是横向合并;

纵向合并使用rbind():total <- rbind(dataframeA, dataframeB) #r是row,所以把两个数据框的行合并了,那就是纵向合并。rbind()的两个数据框必须有相同的列。

  1. 数据集取子集:

选入变量:

newdata <- leadership[,c(6:10)] #所有行,6-10列,注意冒号的用法,是产生6,7,8,9,10,而c()函数,把这五个数变成向量(其实6:10生成的本来就是向量,这里不用c()函数也可以的)。还可以指定向量名称:myvar <- c("q1","q2","q3","q4","q5"); newdata <- leadership[myvar] #使用变量名来选取变量。注意变量名在引号里面。更花哨的写法:myvar <- paste("q",1:5,sep="");newdata <- leadership[myvar] #这里是使用paste()函数来生成变量名。

剔除变量:

myvars <- names(leadership) %in% c("q3", "q4")

newdata <- leadership[!myvars]

解释:

names(leadership)返回包含所有变量名的字符向量;

names(leadership) %in% c("q3", "q4") 返回了一个逻辑型向量,names(leadership)向量中匹配“q3”“q4”的元素值为TRUE,否则为FALSE。所以这个语句返回c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE)

!myvars将逻辑型向量的值反转:c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE)

所以最后一句其实就是:leadership[c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE)],选择了逻辑值为TRUE的列

如果已知q3,q4是第八第九个变量,可以这样:newdata <- leadership[c(-8,-9)] #负号表示剔除,这一点和python不一样,注意一下。

还可以这样:leadership$q3 <- leadership$q4 <- NULL,把q3,q4两列设置成NULL。

选入观测(行):

newdata <- leadership[1:3,] #1-3行,所有列( 2017/04/12 22:29 注意逗号

newdata <- leadership[which(leadership$gender=="M" & leadership$age>30),]

#逻辑比较leadership$gender=="M"生成向量c(TRUE,FALSE,FALSE,TRUE,FALSE);

#逻辑比较leadership$age > 30生成向量c(TRUE,TRUE,FALSE,TRUE,TRUE)

#二者&之后,生成向量c(TRUE,FALSE,FALSE,TRUE,FALSE)

#函数which()给出了参数值为TRUE元素的下标,所以which(c(TRUE,FALSE,FALSE,TRUE,FALSE))生产向量c(1,4) (奇怪,这里明明不用which也可以啊?)

#leadership[c(1,4),]即选择了数据框中第一行和第四行的所有列。

#认真琢磨上述过程,对于理解R语言对数据的处理原理非常有益。


attach(leadership)

newdata <- leadership[which(gender=="M" & age>30),]

detach(leadership)


选择日期区间:

leadership$date <- as.Date(leadership$date,"%m/%d/%y") #转成日期

startdate <- as.Date("2009-01-01")

enddate <- as.Date("2010-01-01")

newdata <- leadership[which(leadership$date>=startdate & leadership$date<=enddate),] #选择日期。还是,不用which也可以

subset()函数

newdata <- subset(leadership,age>=35 | age<=24, select=c(q1,q2,q3,q4)) #subset()函数中,三个参数,第一个指定要选择的数据框,第二个筛选符合条件的行,第三个用select通过变量名选择列;

newdata <- subset(leadership,gender=="M" & age>25,select=gender:q4) #select=gender:q4 表示选择从gender到q4这些列。注意这里没有使用c()函数。刚试了试,用c()也行...另外注意,在subset()里面,第一个参数已经指定了数据框,后面就不用再写leadership$age了,直接写age就行。(subset()函数的参数还是非常喜闻乐见的:数据框,行,列,简洁明了。就是列要用select=这样的形式指定一下需要记住)

1:5和c(1:5)返回的结果是一样的...那么前面那些c(a:b)是不是也可以换成a:b?

随机抽样:sample()函数

mysample <- leadership[sample(1:nrow(leadership),3,replace=FALSE),] #sample()函数3个参数,第一个是要从中抽取的元素构成的向量(就是抽样范围),这个例子中,1:nrow(leadership)指定范围是从1到数据框的行数(1,2,3,...);第二个参数指定抽取数值的个数;第三个参数指定是否放回,这里是无放回的取出。所以sample()函数返回的是一个向量,这里我们用这个向量来索引数据框的行。逗号后面是空的,表示所有列。


  1. 使用SQL语句操作数据框

sqldf包允许我们使用SQL语句操作数据框。

library(sqldf)

newdf <- sqldf("select * from mtcars where carb=1 order by mpg",row.names=TRUE) #row.names=TRUE将原始数据框中的行名延续到了新的数据框中

sqldf("select avg(mpg) as avg_mpg, avg(disp) as avg_disp,gear from mtcars where cy1 in (4,6) group by gear")


文章有问题?点此查看未经处理的缓存