简介:这份《R试题(附带答案)》文档面向准备R语言课程考试、面试复习或基础自测的学习者,以题目加答案解析的形式梳理描述性统计与推断性统计、名义/有序/计数/计量数据类型,以及工作目录查看、head()、ls()、rm()等入门操作。内容还覆盖向量运算、因子创建、矩阵构造与索引、apply类函数应用等常见考点,每题附有答案,便于对照排查知识盲区。压缩包共1个docx文件,约96KB,轻量易取,适合打印练习或在电脑端逐题核对。已有11252人学习下载,说明其题目覆盖面与解析方式具有一定参考价值。读者可借此完成一次从概念辨析到代码输出的系统自测,尤其适合考前快速过一遍基础语法、函数返回值与易错细节,也可作为课堂练习或复习提纲的补充材料。
1. R语言试题到底在考什么:一张卷子背后的一套数据思维
学车前要考科目一,全是选择题,很多人背完就忘,觉得没啥用。真上了路才发现,那些看着死板的判断题,决定了你在路口会不会下意识踩错踏板。R语言试题也是这个性质:它不教你怎么写出漂亮的分析脚本,而是把「这段代码为什么报错」「结果为什么和我手算的不一样」拆成一道道选择题,逼你把判断做对。
这份资料是一套带答案的R语言试题,从最基础的名词(描述性统计、推断性统计、名义数据、计量数据)一路考到R的对象结构、控制流、自定义函数、描述性统计图形、常见概率分布和参数估计。它值得花时间搞懂的理由很朴素:R的报错绝大多数不是算法错,而是类型判断错、结构判断错、下标算错——恰好就是卷子上反复出现的那几个坑。
2. 从「学历」和「身高」说起:四种数据类型为什么决定了后面所有操作
2.1 名义、有序、计数、计量:两组划分先把数据分完
统计学里给数据分类,用的是两刀切。第一刀切出「定性」和「定量」:定性数据描述的是类别,定量数据描述的是数量。第二刀再各自细分——定性数据分成名义数据和有序数据,定量数据分成计数数据和计量数据。
这套划分听着像背书,其实每个名字都在回答一个问题:这个数字能不能做算术。
名义数据是最「弱」的一档。它用数字或文字标记身份,但数字本身没有大小含义。比如一家公司里,1代表行政部、2代表财务部、3代表销售部,这里的1和3之间不存在「3比1多两倍」这回事,把三个部门编码加起来等于6,毫无意义。有序数据比它强一点,类别之间有明确顺序,但相邻两档之间的差距不一定相等,比如满意度分成「不满意、一般、满意」,你知道满意高于一般,却说不清高多少。
计数数据是一颗一颗数出来的,只能是整数,比如某门店一天卖出的手机台数、某路段一小时通过的车次。计量数据是量出来的,可以有小数,比如身高、体重、温度。区分这两个的办法很直接:问一句「这个数能不能出现0.5」。卖手机不能说卖了3.5台,但身高可以说1.75米。
提示:判断数据类型时不要去纠结数字长什么样,只问一句「对它做加减乘除有没有现实意义」。有意义是定量,没意义是定性。
2.2 为什么数据类型是R的「身份证」
R在运行时并不看你给变量起了什么名字,它看的是这个对象身上挂着的类型标记。同样一个1,存成数值就是数值,存成字符就是字符,两者的行为完全不同:数值能求和,字符求和直接报错。
这一点在试卷里有个特别典型的题:
x <- 3 y <- as.character(x) y is.numeric(y)运行结果是:
[1] "3" [1] FALSE前半段输出的"3"带着引号,说明它已经是字符了;后半段is.numeric()返回FALSE,是在确认这个事实。很多人会本能地觉得「3不就是数字吗」,这正是类型概念最容易绊人的地方——值看起来一样,身份已经换了。转换之后,y + 1会报错,而不是得到4。
理解了这层,就能看懂试卷里另一道题为什么要考L <- 3 == 5。==是一个比较运算符,它不赋值数字,只回答是或否,所以L是逻辑变量,值为FALSE。这里还藏着一个新手常踩的坑:R里判断相等用两个等号,一个等号是赋值。写成L <- 3 = 5直接就是语法错误。
2.3 描述性统计和推断性统计:一条线划开两半
试卷第一题问「用图或表描述数据属于什么」,答案是描述性统计。第二题紧接着问统计学分成哪两部分,答案是描述性统计和推断性统计。这两道题挨在一起不是凑数,它们划的是整门课的分界线。
描述性统计做的事,是把手上这堆数据压缩成几个能看懂的数字或图形:平均数、方差、频数表、直方图。它只对你手里的样本负责,不往外推。推断性统计做的事正好相反,它拿样本去猜总体,用一小部分信息去推未知的全貌,代价是要承担犯错的风险,所以才有置信区间、显著性水平这些概念的用武之地。
打个比方,描述性统计像体检报告——血压多少、心率多少,白纸黑字写清楚;推断性统计像医生看完报告后说「你大概率没什么问题」,这句话有依据,但不是百分之百确定。两者用的是同一批数据,承担的责任完全不同。
3. R的对象家族:向量、矩阵、数组、列表、数据框到底差在哪
3.1 向量:R里最小的积木,循环补齐是它的隐藏规则
向量是同类型元素排成的一队。R里几乎所有运算都是按向量设计的,这也是它和很多语言最不一样的地方——你写c(1, 2, 3) * 2,得到的是每个元素各乘2,不需要写循环。
当两个长度不同的向量做运算时,R会启动「循环补齐」:短的自动重复自己,直到长度对上。试卷里那道题就是在考这个:
c(1, 2, 3, 4, 5) + c(20, 200) # 短向量循环成 20 200 20 200 20,逐位相加 # 结果:[1] 21 202 23 204 25注意这里没有报错。R不会因为长度不整除就停下来,它只会给一条警告(warning),然后照算不误。这个设计的初衷是方便做批量运算,可一旦你没意识到它在补齐,结果就会莫名其妙。比如你以为自己在做两组的对应相加,实际上第二组被重复使用了两遍半。
真正会报错的情况是长度不成整数倍,比如长度5加长度2,5不是2的倍数,R会给警告说长的对象长度不是短的对象长度的倍数,但仍然返回结果。要判断代码是不是踩了补齐,最稳的办法是在关键步骤打印length()核对一下。
3.2 矩阵与数组:给向量加一层「格子」
矩阵就是二维的、同类型的表格。R里创建矩阵最常用的函数是matrix(),它有一个默认行为必须记住:按列填充。
# 12个数,3行,默认按列填 A <- matrix(1:12, nrow = 3) A # [,1] [,2] [,3] [,4] # [1,] 1 4 7 10 # [2,] 2 5 8 11 # [3,] 3 6 9 12如果想让数字横着排,得显式加一句byrow = TRUE。这个参数是新手最容易漏的,漏了之后矩阵转置了却浑然不觉,后面所有取子集的操作全跟着错。
试卷里有一道题问:要生成上面这个矩阵,可以用哪些写法?答案是array(1:12, c(3, 4))、A <- 1:12; dim(A) <- c(3, 4)、matrix(1:12, nrow = 3)、matrix(1:12, nrow = 3, ncol = 4)、array(1:12, dim = c(3, 4))全都行。这五个写法之所以等价,是因为它们本质上都在做同一件事——给一维的12个数挂上一个维度属性。dim()不是创建新对象,而是给已有对象贴标签,贴完之后R就把它当矩阵对待了。
取子集用方括号加行列位置,逗号左边是行、右边是列,留空表示「全要」:
A[2:3, c(3, 4)] # 第2、3行 与 第3、4列交叉的部分 # [,1] [,2] # [1,] 8 11 # [2,] 9 12 A[, 1] # 第一列全部,返回的是一个向量 # [1] 1 2 3这里的分寸感很重要:只取一列时,结果降维成向量,不再是矩阵。想保住矩阵结构,得加drop = FALSE。这个细节在后面做数据框操作时会反复出现。
3.3 列表与数据框:允许「混装」的两个盒子
矩阵有个硬性要求:所有元素类型一致。可现实数据从来不是这样的——一列是姓名(字符),一列是年龄(数值),一列是部门(因子)。这时候就需要能装不同东西的容器。
列表是最宽松的容器,里面什么都能塞:向量、矩阵、因子、甚至另一个列表。取元素用双方括号[[ ]],取出来的是元素本身;用单方括号[ ]取出来的还是一个列表。
数据框本质上就是一个被规整过的列表:每一列是一个向量,所有列长度相等,但列与列之间类型可以不同。这一点试卷里专门考过——矩阵要求元素类型一致,数据框不要求,因为它的列本质是向量,一列内类型一致就够了,列与列之间可以各管各的。这也是数据框能对应现实表格的原因:一列姓名、一列年龄、一列性别,本来就该是不同类型。
数据框还有个隐形福利:它给每一列起了名字,所以可以用列名访问。df$Height、df[["Height"]]、df[, "Height"]取出来都是向量,而df["Height"]取出来是只有一个列的数据框。差别看着小,用错了后面全乱。
3.4 索引取子集:三种括号各管一件事
R的括号长得像,分工很清楚:()是调用函数和改变运算优先级,[]是取子集,[[]]是从容器里掏出元素本身。这三者在列表和数据框上体现得最明显。
还有一类下标容易被忽略:负号表示排除。
v <- 10:5 # 10 9 8 7 6 5 v[-c(1, 5)] # 排除第1个和第5个,剩 9 8 7 5 v[-(1:5)] # 排除前5个,只剩 5负下标不能和正下标混用,比如v[c(1, -2)]会直接报错。这条规则在选择题里出现频率不低,因为很多人凭直觉以为负号是「倒着数」。
另一个高频点是which():它返回的不是值,是位置。which(2:8 > 5)先把2:8逐个和5比,得到一串FALSE FALSE FALSE FALSE TRUE TRUE TRUE,which()再把这串逻辑值里TRUE的位置挑出来,返回5 6 7。所以它的结果永远可以用来当下标,v[which(...)]这种写法就是这么来的。
4. 常见误区:这些题看着像送分,其实最容易翻车
4.1 误区一:把编码当数字,对名义数据求平均
易混点:部门编码1、2、3,学历编码1、2、3,看着都是数字,就直接mean()。
为什么混:数据录入时为了省事,类别全用数字代替,存进R里天然就是数值型。函数不会拦你,它老老实实把1、2、3加起来除以3,给你一个2——一个在现实中不存在的「平均部门」。
怎么区分:问自己这个数字做加法有没有意义。没有意义,就必须在导入后立刻把它声明成因子,factor(x, levels = c(1, 2, 3), labels = c("行政部", "财务部", "销售部")),让R知道这是分类不是量。声明之后,mean()会直接报warning并返回NA,这就是R在替你踩刹车。
4.2 误区二:以为df["Height"]和df$Height是一回事
易混点:三种取法写出来只差一两个符号,结果一个是向量一个是数据框。
为什么混:很多语言里「取一列」只有一种结果,R却给了两条路,而且都不报错,只是结构不同。等你把它传给mean()或者hist(),才发现一个正常一个报错。
怎么区分:记住方括号里带逗号的、双层的,掏出来的是内容本身;单层方括号加列名,切出来的仍是数据框的一片。判断办法是class()一下,一眼就清楚。做图、做计算用向量,需要保留表格结构往下传(比如merge、subset)时用数据框。
4.3 误区三:levels和labels当成可有可无的装饰
易混点:题目里「只想对1和2两个部门做分类统计」,选项里有的写levels = c(1, 2, 3),有的写levels = c(1, 2)。
为什么混:两个参数都出现在factor()里,看着像同义反复。
怎么区分:levels决定「哪些值算有效」,labels决定「有效值显示成什么名字」。写levels = c(1, 2),等于宣布3不是合法类别,原本编码为3的行会被悄悄变成NA——这一步不会报错,只会在你统计总数时发现少了一批人。想保留三类只是显示成两个名字,levels就得写全三项。至于gl(),那是专门用来生成规则因子序列的函数,不是用来转换已有数据的,选项里拿它冒充factor()是最常见的干扰项。
4.4 误区四:1:n-1和1:(n-1)分不清
易混点:冒号的优先级高于减号,1:n-1会被解析成(1:n) - 1。
为什么混:数学书写习惯了「1到n-1」,眼睛看到的就是这个意思,可R不这么读。当n <- 3时,1:n-1先算出1 2 3,再整体减1,得到0 1 2,开头多了一个0。
怎么区分:凡是冒号后面跟运算,一律加括号。1:(n-1)才是想要的结果。这类错误不会报错,只会让向量悄悄多一位或少一位,然后在后续的下标引用里引发一连串错位,属于典型的「当时看不出来,事后查半天」。
4.5 误区五:四种平均数随手抓一个用
易混点:算术、加权、几何、调和,四个都叫「平均数」。
为什么混:平时说「平均」默认就是加起来除以个数,可有些场景这么算出来是错的,而且错得不明显。
怎么区分:看分母是什么。分母是「个数」,用算术平均;分母是「权重」(股数、学分、占比),用加权平均;变化率连乘、增长率求平均,用几何平均;给出的是「每单位对应的量」(速度、单价)而总量固定,用调和平均。判断口诀是:先想清楚你平均的到底是「每一份」还是「每一次」。试卷里那道「前半段时速60、后半段时速30,两段距离相等」的题,答案就是调和平均——因为时间是按距离反比分配的,不能直接对两个速度取算术平均。同一道题如果改成「前半段开1小时、后半段开1小时」,那就变成算术平均了。
注意:R里求中位数的函数是
median(),不是media()。少一个字母就是「找不到函数」的报错,考卷上把它写成media()属于典型笔误,实际敲代码时却真有人这么写。
5. 描述性统计与概率分布:平均数不止一种,分布也不止一种
5.1 定性数据的两套描述工具:一张表、三张图
定性数据没法求均值,所以它的描述方式只有两条路:数频数和画图。
数频数用table(),它返回每个类别出现了多少次。想看占比就再套一层prop.table():
dept <- factor(c("行政", "财务", "销售", "行政", "行政", "财务")) table(dept) # 各类别的绝对次数 prop.table(table(dept)) # 各类别的相对占比,加起来等于1图形这边有三样:条形图barplot()、饼图pie()、帕累托图。前两个好理解,帕累托图其实就是把条形图按频数从高到低排序,再叠一条累计占比曲线——它背后的经验法则是「少数类别贡献了大部分数量」,用来快速找出重点。试卷里问定性数据的图形有哪几种,答案就是条形图、饼图和帕累托图,对应的函数是barplot()和pie()。
5.2 定量数据的图形三件套:直方图、茎叶图、箱线图
定量数据可以画的图多得多,但最基础的是三个:直方图hist()看分布形状,茎叶图stem()既看形状又保留原始数值,箱线图boxplot()看中位数、四分位数和异常值。
x <- c(21, 8, 2, 5, 11) hist(x) # 分组看频数分布 stem(x) # 文本形式保留每个原始值 boxplot(x) # 五数概括 + 离群点标记三者的分工可以用一句话记住:直方图告诉你「数据堆在哪儿」,茎叶图告诉你「堆在那儿的到底是哪些数」,箱线图告诉你「有没有人掉队」。样本量很小的时候茎叶图尤其好用,因为它不丢信息;样本量上千之后茎叶图会印满屏幕,那就该换直方图了。
5.3 四种平均数:本质是「谁当分母」的问题
平均数的选择不是数学游戏,它取决于你手上拿的是什么口径的数据。
加权平均最常见,总评成绩就是典型:平时占10%、实验作业占20%、期末占70%,直接三项相加除以3是错的,必须按权重乘完再除。股票的平均成本也是加权——买了1000股10元的、2000股15元的,平均成本是(1000×10 + 2000×15) / 3000,不是(10+15)/2。后者的错误在于把「股数」这个真实权重抹平了。
几何平均处理的是连乘关系。周一到周五的销售目标如果是在前一天基础上分别增长10%、12%、8%、11%、9%,那平均增长率不是把这五个百分比加起来除以5,而是把它们各自加1之后连乘、再开5次方、最后减1。原因是增长是叠在上一天的基础上发生的,加法在这里会高估。
调和平均处理的是「固定总量下的单位量」。同样花1元钱在三个市场买单价不同的水果,问平均每千克多少钱,答案是总钱数除以总重量,而总重量是1/单价之和,这就落到调和平均上了。同理,两段等距离的路程求平均速度,也是调和平均。
提示:拿不准的时候,先写出「总量 ÷ 份数」这个原始式子,再看份数是怎么来的。份数由权重决定就用加权,由比率倒数决定就用调和,由连乘决定就用几何。
5.4 六个常见分布和它们的两把尺子
试卷里反复出现的分布有六个,分成离散和连续两组。
离散组:二项分布、泊松分布、超几何分布。二项分布描述n次独立重复试验里成功的次数,期望是np,方差是np(1-p)。泊松分布描述单位时间或单位空间内稀有事件发生的次数,它有个漂亮的性质——期望和方差都等于λ。超几何分布和二项分布的关系是试卷爱考的:二项分布对应有放回抽样,每次试验条件不变;超几何分布对应无放回抽样,抽走一个总体就变了一点。样本量相对总体很小的时候,两者结果几乎一样,所以实际工作中常拿二项近似超几何。
连续组:均匀分布、正态分布、指数分布。均匀分布在区间[a, b]上概率密度处处相等,期望是(a+b)/2,方差是(b-a)²/12——那个12是推导出来的常数,不用记来源,记住形式即可。正态分布由均值μ和方差σ²两个参数完全确定,期望就是μ、方差就是σ²。指数分布的期望是1/λ,方差是1/λ²。
指数分布和泊松分布的关系值得单独说一句:泊松描述的是「一段时间内事件发生几次」,指数描述的是「两次事件之间隔多久」,前者是计数,后者是等待时间,两者共用同一个λ,但含义相反。某洗车店每小时平均来10辆车,那么车辆到达的间隔就服从λ=10的指数分布,平均间隔是1/10小时,也就是6分钟。这里最容易错的是把平均间隔写成10——λ是「单位时间多少次」,取倒数才是「每次多久」。
5.5 统计三大分布与抽样:样本均值自己也有分布
到这里还差一块拼图:抽样分布。它的核心问题是——我从总体里抽n个样本算出一个均值,这个均值本身会不会波动?答案是会,而且它自己服从一个分布。
如果总体是N(μ, σ²),那么样本均值服从N(μ, σ²/n)。注意方差被除以了n,这解释了一个日常经验:样本量越大,样本均值越稳定。n从100涨到400,均值的标准差减半,这也是为什么调查样本量翻四倍才能把误差压一半。
由正态分布还能派生三个分布,试卷称之为统计三大分布:卡方分布、t分布、F分布。卡方分布是若干个标准正态变量的平方和,常用来构造方差的区间估计;t分布长得像正态但尾巴更厚,专门用于总体方差未知时对均值做推断;F分布是两个卡方分布各自除以自由度之后的比值,用于比较两组方差。这三个分布是后面做假设检验的全部工具箱,试卷把它们和「均匀、正态、指数」放在一起做干扰项,就是要你分清哪些是描述数据的分布、哪些是描述统计量的分布。
顺带提一句点估计。试卷问常见点估计方法有哪几种,答案是矩估计法、极大似然估计法和最小二乘估计法。矩估计的思路最直白:用样本矩去估计总体矩,样本均值估总体均值、样本方差估总体方差,拿已知推未知。
6. 什么时候该刷这套题、什么时候别刷:一份边界判断
这套题的价值边界其实很清楚,用一张表能说透。
| 场景 | 适不适合 | 原因 |
|---|---|---|
| 刚学完数据类型和对象结构,想自查有没有概念漏洞 | 适合 | 题目密度高,覆盖了名义/有序、向量/矩阵/列表/数据框这些最容易含混的点 |
| 考试前想快速过一遍函数名和参数 | 适合 | head、ls、rm、factor、apply、table、hist 这些高频函数几乎都出现了 |
| 想搞懂某个函数背后的算法原理 | 不适合 | 卷子只给结论和答案,不展开推导,需要另找教材 |
| 想做真实数据分析项目练手 | 不适合 | 题目都是碎片化的单点验证,缺少完整的数据清洗到建模流程 |
| 已经能熟练写R脚本,只想查漏补缺 | 部分适合 | 可以只挑矩阵取子集、因子转换、apply 家族这几块看 |
判断自己该不该刷,有个简单办法:随便挑一道题,先别管答案,把代码敲进控制台跑一遍,看结果和你脑子里预判的是否一致。一致,说明这块你已经过关,可以跳过;不一致,那就是你要补的洞。这个自测方式比从头到尾刷一遍效率高得多,因为你的时间应该花在「预判失败」的地方,而不是「已经会」的地方。
至于什么时候别刷,我的建议是:如果你连向量和列表都还分不清,先别碰最后那几章的概率分布和参数估计。那部分题目默认你已经能熟练操作数据结构,直接上手只会变成背答案。反过来,如果你正在准备一场以选择题为主的考核,这套题的性价比就很高——它把出题人爱设的陷阱都摊在明面上了,比如循环补齐、单双方括号、levels截断、冒号优先级,这些点看一遍答案记不住,必须自己踩一次。
我自己的习惯是:每次遇到一段结果和预期不符的代码,先不急着改,而是把中间每一步的class()、length()、str()打出来看一遍。这个动作最早就是从做这类题养成的——当时错了一道df["Height"]的题,明明觉得取的就是那一列,mean()却报错,查了半天才发现拿到的是数据框不是向量。从那以后我每次写取子集的代码,都会先跑一遍class()确认结构,宁可多打一行,也不让它在几十行之后才炸出来。
希望这套题也能帮你把那些「以为懂了其实没懂」的地方提前暴露出来,完整题目和答案都在资料里,需要的话去下载页自取就好。
本文还有配套的精品资源,点击获取