5. 来点实用的:df = data frame

前言

在第3章,讲到了矩阵matrix和向量vector,矩阵和向量都只能包含某一种数据类型,而在实际应用中,这种情况比较少见。

当我们做一项数据调查时,调查报告通常不可能只含有数值型数据或者字符型数据,而是包含各种数据类型(做分析时需要对目录数据进行编码,这部分内容会在python分析基础中讲到)。因此,我们需要一种新的容器类型——data frame。

有人把data frame翻译为数据帧,这种译法是不准确的,尤其是考虑到“帧”的定义和data frame的含义的差别。也有人完全按照字面意思把它翻译成数据框架,我感觉有些画蛇添足,把原本不难理解的东西复杂化。

 ***为了简化编辑文本,后面用 df 代替 data frame(代码中常常这么做)。***

概述

本章主要讲了:

  • 如何理解dataframe,
  • 如何载入并使用R的内置数据集mtcars,
  • 怎样从多个向量创建一个df,
  • 两种方法创建df的子集,
  • 怎样排序

df到底是什么

其实很简单,用一个例子就能解释明白:中学时老师统计的期末成绩单就是一个df,通常一个Excel表格中包含以下内容:

  • 序号:整型
  • 学号:字符型
  • 学生姓名:字符型
  • 分数:浮点型

在实际操作中,我们通常读取一个Excel表单或者一个csv文件,并将这个文件赋值给一个变量(df或者data),后期对文件的操作可以通过变量名来进行。需要注意的是,df的每一行表示不同的观测对象,每一列表示一个定语或变量。在成绩单里,每个学生都是一个被观测的个体,而各科成绩表示不同的定语(Attribute),定语是用来描述观测对象的特征的。

下面我将采用R语言内置的数据集mtcars(motor trend car road tests)来做演示。

载入内置数据集mtcars

首先打开RStudio,用data()函数载入数据集:

#载入数据
data("mtcars")

#输出前后五行
head(mtcars, 5)
tail(mtcars, 5)
mtcars前五行

通过前五行数据,我们可以看到,每行表示不同的汽车型号,列表示每个汽车型号的不同特征,例如排量,马力,气缸数等等。

查看mtcars的结构

通常在获取一个数据集后,我们需要了解它的结构,例如一共有几行,有哪些列,列的名字,每列的数据类型等。查看df的结构,需要str()函数。

str(mtcars)
mtcars的结构

输出结果表示,mtcars一共有32行(observations),和11列(variables)。
$符号后面是列名,一共11个,且mtcars中所有的数据类型都是numerical。

创建一个df

前面使用了内置数据集,接下来可以使用data.frame()自己创建一个,括号中填入不同的向量,这些向量必须包含相同的元素数量。
*注意区分R和python在创建df时的不同语法

我们以太阳系内八大行星为例,建立一个df,包含行星的名字,类型(岩质行星还是气态巨行星),相对地球直径的比值,相对地球公转周期的比值以及是否含有星环(不止土星有星环)。

# 先定义所用到的向量
name <- c("Mercury", "Venus", "Earth", 
          "Mars", "Jupiter", "Saturn", 
          "Uranus", "Neptune")
type <- c("Terrestrial planet", 
          "Terrestrial planet", 
          "Terrestrial planet", 
          "Terrestrial planet", "Gas giant", 
          "Gas giant", "Gas giant", "Gas giant")
diameter <- c(0.382, 0.949, 1, 0.532, 
              11.209, 9.449, 4.007, 3.883)
rotation <- c(58.64, -243.02, 1, 1.03,
              0.41, 0.43, -0.72, 0.67)
rings <- c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE)

# 用向量创建df
planets_df <- data.frame(name, type, diameter, rotation, rings)
planets_df
行星数据

观察一下我们创建的df,不难发现每个向量就是df中的每一列。(在python中有类似的用法,即通过字典dictionary创建df,参见python教程。)

选df中的元素

跟矩阵和向量类似,我们可以选择df的特定行和 / 或列。利用中括号,在逗号的左边填入想选择的行,右边填入列。这个用法跟前面矩阵的元素选择重复,这里就省略了。

这里介绍另外一种方法,只用列名选择某个特定的列:
df$colname
输出的结果是一个向量,可以用class()函数验证向量元素的类型。

rings_vec <- planets_df$rings
rings_vec
class(rings_vec)

更进一步,如果我们想选出有星环的行星,可以通过以下操作:

planets_df[rings_vec, ]
有星环的行星

可以看出,我们筛选出了rings列中,值为TRUE的所有行。

那么能否筛选不带星环的行星?
方法很简单,只需要在中括号中加入一个!

planets_df[ !rings_vec, ]
没有星环的行星

*注意:由逻辑值组成的列通常被用来筛选符合某些条件的行,若没有由逻辑值组成的列,我们可以通过逻辑运算符自己建立一个筛选标准

现在我们尝试找出影响行星是否有星环的因素。
对比这两个结果,可以发现太阳系中的岩态行星都没有星环,而气态巨行星都有星环。因此我们可以猜测,影响一个行星是否有星环的因素是行星的类型。当然这只是一个假设,要想验证这个假设在银河系甚至可观测宇宙是否成立,我们需要更多数据来进行假设检验,这部分的内容需要懂点统计学,后面会讲到。

使用subset()创建子集

上一步实际上是给我们的数据集创建了一个子集,用来过滤掉一部分不需要i的数据。现在介绍一种更高效、更普适的方式:

subset(数据集,subset = 某些条件)

借助第二个arg,我们可以根据“某些条件”来选择。这里的条件覆盖较广的范围,不再局限于逻辑值。

subset(planets_df, subset = rings == TRUE) 

*注意:这里的‘单等于号’表示赋值,‘双等于号’表示逻辑判断

有星环的行星子集

结果跟前面一致,我们的方法都是对的。

现在试试用numerical数据作为筛选条件,选出直径比地球直径大的行星:

subset(planets_df, subset = diameter > 1)

直径大于地球的行星

*“直径大于地球的行星都是气态巨行星,我想这是个偶然现象”——典型的假设检验中的原假设H0:p = 0,H1则为p > 0

排序

排序要用到order()函数:

order(..., na.last = TRUE, decreasing = FALSE,
      method = c("auto", "shell", "radix"))

*注意:decreasing默认为假,也就是说如果不填这个arg,order()函数会进行升序排列

  • 首先,给向量的元素做排序,
a <- c(3, 2, 6, 1, 5, 4)
a[order(a)]
从小到大排序
a[order(a, decreasing = TRUE)]
从大到小排序
  • 接下来,将df按照直径大小递增的顺序进行排序:
increasing_diameter <- order(planets_df$diameter)
planets_df[increasing_diameter, ]

直径递增

*注意:索引也同样发生了变化,这说明df的索引是在创建df时就已经确定了,不会因为重新排序而改变,有别于Excel

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容