用R语言做数据清理之一:数据的清理
数据的清理
一份好的,干净而整洁的数据至少包括以下几个要素:
1、每一个观测变量构成一列
2、每一个观测对象构成一行
3、每一个类型的观测单元构成一个表
就像我们最常接触的鸢尾花数据:
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
每一列就是观测的指标:花瓣长度,花瓣宽度,萼片长度,萼片宽度,种类;每一行就是一株鸢尾花的观测值,构成整张表的元素就是四个数值变量,一个分类分类变量。
然而出于排版的考虑我们抓下来的数据往往不是那么的友好,比如说我们可以看到的数据通常是这样的:
## religion <10k 10k-50k 50k-100k
## 1 Agnostic 12 31 23
## 2 Buddhist 58 43 43
## 3 Catholic 79 56 23
而不是:
## religion income freq
## 1 Agnostic <10k 12
## 2 Agnostic 10k-50k 58
## 3 Agnostic 50k-100k 79
## 4 Buddhist <10k 31
当然,除了这种把列表每一列代表一些数值这种情况外,还有多个变量储存为一列(比如列表不仅以"<10k","10k-50k","50k-100k"做表头,甚至还加上性别信息"m<10k","m10k-50k","m50k-100k","f<10k","f10k-50k","f50k-100k",其中m代表男性,f代表女性),还有更过分的将列表的变量不仅储存在列中,行中也有统计变量。
面对这些不好的table,我们首先要做的就是数据管理,将数据整理为一个干净的数据集。
数据管理
按照en:DAMA的定义:“数据资源管理,致力于发展处理企业数据生命周期的适当的建构、策略、实践和程序”。这是一个高层而包含广泛的定义,而并不一定直接涉及数据管理的具体操作(如关系数据库的技术层次上的管理)。我们这里主要讲述对于数据的变量命名与数据的合并,旨在方便数据共享。
数据管理首先要做的就是大致上了解你的数据,比如有什么样的变量,每一行大致长成什么样,最常用的就是head(),tail().
我们要做的基本上就是这么几项工作:
给每一个变量命名,而不是V1,V2,如果有必要可以给出code book。
每个变量名最好具有可读性,除非过长,否则不要用缩写,例如AgeAtDiagnosis这个命名远好于AgeDx。
通常来说,最好将数据放在一张表里面,如果因为数据过多,项目过杂,分成了几张表。那么一定需要有一列使得这些表之间能够连接起来,但尽量避免这样做。
我们以UCI的Human Activity Recognition Using Smartphones Data Set 为例来看看数据是如何变成一个基本符合要求的数据。这个数据我们已经下载下来了,其中关于数据的详细信息可以参阅read me文档,由于UCI的数据通常都是一个基本合乎规范的数据集(主要是指它的数据集的变量名都是以V1,V2来命名的)加上一个code book。那么我们看看各个数据的名称(在feature文件里)
setwd("F:/coursera/Data Science/peer assignment/get clean and tidy data/UCI HAR Dataset")name <- read.table("./features.txt", stringsAsFactors = F)
head(name)
## V1 V2
## 1 1 tBodyAcc-mean()-X
## 2 2 tBodyAcc-mean()-Y
## 3 3 tBodyAcc-mean()-Z
## 4 4 tBodyAcc-std()-X
## 5 5 tBodyAcc-std()-Y
## 6 6 tBodyAcc-std()-Z
我们可以看到各个特征的名称直接标在数据上是非常不友善的,我们为了让他具有可读性,我们以展示在我们眼前的6个数据为例:
variablename <- head(name)# 将标签中的大写字母转为小写,我们这里没有所以不再赋值,如果需要全变为大写,可以使用touppertolower(variablename$V2)
## [1] "tbodyacc-mean()-x" "tbodyacc-mean()-y" "tbodyacc-mean()-z"
## [4] "tbodyacc-std()-x" "tbodyacc-std()-y" "tbodyacc-std()-z"
# 将变量名分离成3部分splitNames <- strsplit(variablename$V2, "-")splitNames[[1]]
## [1] "tBodyAcc" "mean()" "X"
# 将变量名合成有意的名称named <- function(x) { rr <- paste(x[2], x[1], "-", x[3],sep = "")
chartr("()", "of", rr)
}
sapply(splitNames, named)
## [1] "meanoftBodyAcc-X" "meanoftBodyAcc-Y" "meanoftBodyAcc-Z"
## [4] "stdoftBodyAcc-X" "stdoftBodyAcc-Y" "stdoftBodyAcc-Z"
用这样的名字给数据集命名就感觉舒服多了,我们将一些R中对字符串常用的操作函数总结如下,方便我们对数据名称的修改:
sub:替换字符串中的第一个模式为设定模式(pattern).
gsub:全局替换字符串中的相应模式
grep,grepl:这两个函数返回向量水平的匹配结果,grep仅返回匹配项的下标,而grepl返回所有的查询结果,并用逻辑向量表示有没有找到匹配。
nchar:统计字符串单字数目
substr:取子串
paste:将字符串链接起来,sep参数可以设置连接符
str_trim:去掉字符串空格
变量的名称建议满足如下要求:
英文变量名尽可能用小写
尽可能的描述清楚变量特征 (Diagnosis versus Dx)
不要太复杂
不要有下划线、点、空格
字符型变量应该满足:
是因子类型的应该转化为factor
因子尽可能具有一定的描述性 (例如:如果0/1表示真假,那么用TRUE/FALSE代替0/1;在表示性别时用Male/Female代替M/F)
接下来我们讨论数据集的合并,主要使用函数merge。
我们以下面两个数据集的合并为例:
df1 <- data.frame(id = sample(1:10), reviewer_id = sample(5:14),time_left = sample(1321:1330),
x = rnorm(10))df2 <- data.frame(id = sample(1:10), answer = rep("B", 10),time_left = sample(321:330),
y = rnorm(10))
head(df1, n = 3)
## id reviewer_id time_left x
## 1 3 9 1326 -0.9232
## 2 10 5 1322 2.5069
## 3 1 14 1330 2.2478
head(df2, n = 3)
## id answer time_left y
## 1 1 B 329 0.8180
## 2 10 B 327 1.4639
## 3 9 B 323 0.8141
merge函数调用格式为:
merge(x, y, by = intersect(names(x), names(y)),
by.x = by, by.y = by, all = FALSE, all.x = all, all.y = all,
sort = TRUE, suffixes = c(".x",".y"),
incomparables = NULL, ...)
参数说明:
x,y:两个数据框
by, by.x, by.y:指定用于合并的列的名称。
all,all.x,all.y:默认的all = FALSE相当于自然连接, 或者说是内部链接. all.x = TRUE是一个左连接, all.y = TRUE是一个又连接, all = TRUE 相当于一个外部链接.
仔细观察下面3个例子你就会发现其中的奥秘:
mergedData <- merge(df1,df2,by.x="reviewer_id",by.y="id",all=TRUE)
head(mergedData)
## reviewer_id id time_left.x x answer time_left.y y
## 1 1 NA NA NA B 329 0.8180
## 2 2 NA NA NA B 330 -0.7706
## 3 3 NA NA NA B 325 -0.4851
mergedData <- merge(df1,df2,by.x="id",by.y="id",all=TRUE)
head(mergedData)
## id reviewer_id time_left.x x answer time_left.y y
## 1 1 14 1330 2.24783 B 329 0.8180
## 2 2 12 1324 1.03181 B 330 -0.7706
## 3 3 9 1326 -0.92317 B 325 -0.4851
## 4 4 7 1321 -0.07841 B 322 0.1801
mergedData2 <- merge(df1,df2,all=TRUE)
head(mergedData2)
## id time_left reviewer_id x answer y
## 1 1 329 NA NA B 0.8180
## 2 1 1330 14 2.2478 <NA> NA
## 3 2 330 NA NA B -0.7706
在plyr包中还提供了join,join_all,arrange等函数来实现表的连接,但我想merge这个函数已经足够用了,所以我们不在多说。当然,在极少数特别好的情况下(比如列的变量是一致的,或者行的观测个体是一致的时候)rbind,cbind也是有用的。
有些时候我们会遇到一些特殊的字符串:日期。R中提供了各式各样的函数来处理时间:
Sys.setlocale("LC_TIME", "C")
## [1] "C"
x <- c("1jan1960", "2jan1960", "31mar1960", "30jul1960")z <- as.Date(x, "%d%b%Y")
format(z, "%a %b %d")
## [1] "Fri Jan 01" "Sat Jan 02" "Thu Mar 31" "Sat Jul 30"
weekdays(z)
## [1] "Friday" "Saturday" "Thursday" "Saturday"
julian(z)
## [1] -3653 -3652 -3563 -3442
## attr(,"origin")
## [1] "1970-01-01"
transform(z, weekend = as.POSIXlt(z, format = "%Y/%m/%d")$wday %in% c(0, 6))
## X_data weekend
## 1 1960-01-01 FALSE
## 2 1960-01-02 TRUE
## 3 1960-03-31 FALSE
## 4 1960-07-30 TRUE
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
在当今这个数据驱动的时代,几乎每一个业务决策都离不开对数据的深入分析。而其中,指标波动归因分析更是至关重要的一环。无论是 ...
2025-02-18当数据开始说谎:那些年我们交过的学费 你有没有经历过这样的场景?熬了三个通宵做的数据分析报告,在会议上被老板一句"这数据靠 ...
2025-02-17数据分析作为一门跨学科领域,融合了统计学、编程、业务理解和可视化技术。无论是初学者还是有一定经验的从业者,系统化的学习路 ...
2025-02-17挖掘用户价值本质是让企业从‘赚今天的钱’升级为‘赚未来的钱’,同时让用户从‘被推销’变为‘被满足’。询问deepseek关于挖 ...
2025-02-17近来deepseek爆火,看看deepseek能否帮我们快速实现数据看板实时更新。 可以看出这对不知道怎么动手的小白来说是相当友好的, ...
2025-02-14一秒精通 Deepseek,不用找教程,不用买资料,更不用报一堆垃圾课程,所有这么去做的,都是舍近求远,因为你忽略了 deepseek 的 ...
2025-02-12自学 Python 的关键在于高效规划 + 实践驱动。以下是一份适合零基础快速入门的自学路径,结合资源推荐和实用技巧: 一、快速入 ...
2025-02-12“我们的利润率上升了,但销售额却没变,这是为什么?” “某个业务的市场份额在下滑,到底是什么原因?” “公司整体业绩 ...
2025-02-08活动介绍 为了助力大家在数据分析领域不断精进技能,我们特别举办本期打卡活动。在这里,你可以充分利用碎片化时间在线学习,让 ...
2025-02-071、闺女,醒醒,媒人把相亲的带来了。 我。。。。。。。 2、前年春节相亲相了40个, 去年春节相亲50个, 祖宗,今年你想相多少个 ...
2025-02-06在数据科学的广阔领域中,统计分析与数据挖掘占据了重要位置。尽管它们常常被视为有关联的领域,但两者在理论基础、目标、方法及 ...
2025-02-05在数据分析的世界里,“对比”是一种简单且有效的方法。这就像两个女孩子穿同一款式的衣服,效果不一样。 很多人都听过“货比三 ...
2025-02-05当我们只有非常少量的已标记数据,同时有大量未标记数据点时,可以使用半监督学习算法来处理。在sklearn中,基于图算法的半监督 ...
2025-02-05考虑一种棘手的情况:训练数据中大部分样本没有标签。此时,我们可以考虑使用半监督学习方法来处理。半监督学习能够利用这些额 ...
2025-02-04一、数学函数 1、取整 =INT(数字) 2、求余数 =MOD(除数,被除数) 3、四舍五入 =ROUND(数字,保留小数位数) 4、取绝对值 =AB ...
2025-02-03作者:CDA持证人 余治国 一般各平台出薪资报告,都会哀嚎遍野。举个例子,去年某招聘平台发布《中国女性职场现状调查报告》, ...
2025-02-02真正的数据分析大神是什么样的呢?有人认为他们能轻松驾驭各种分析工具,能够从海量数据中找到潜在关联,或者一眼识别报告中的数 ...
2025-02-01现今社会,“转行”似乎成无数职场人无法回避的话题。但行业就像座围城:外行人看光鲜,内行人看心酸。数据分析这个行业,近几年 ...
2025-01-31本人基本情况: 学校及专业:厦门大学经济学院应用统计 实习经历:快手数据分析、字节数据分析、百度数据分析 Offer情况:北京 ...
2025-01-3001专家简介 徐杨老师,CDA数据科学研究院教研副总监,主要负责CDA认证项目以及机器学习/人工智能类课程的研发与授课,负责过中 ...
2025-01-29