考察点
- 总结一下python中元组、列表、字典、集合的异同点。考察对python基础部分的认知程度,此题是入门基础题。
- Python创建函数的方式有哪几种?根据你的认识写出2个案例。本题考察对python函数的应用,因为我们在使用python的过程中是会非常多的使用函数的,很多小模块我们都会优先封装在函数里,进行重复调用。
- 概述pandas的数据合并及数据映射的几种方法。本题考察大家是否有用python做数据处理的基本条件。
- 简要说明你在用python做数据清洗时的流程及实现方法。本题考察大家对数据清洗的认知及python操作的流程。
- 用python随机生成某月1-30号每天的销售额数据,并按照周聚合,同时用任意python作图库做图。本题考察python基础随机数的生成,聚合函数,简单作图的知识点,也是用python做数据分析中常用的知识点。
解答
1.总结一下python中元组、列表、字典、集合的异同点。
2.Python创建函数的方式有哪几种?根据你的认识写出2个案例。
方法1:
def functionname( parameters ):
"函数_文档字符串"
function_suite
return [expression]
案例:
# 创建函数
def func():
if x<100:
y = 1
elif x < 500 :
y = 2
else :
y = 3
return y
#调用函数
x = 800
func(x)
方法2:匿名函数lambda
lambda [arg1 [,arg2,.....argn]]:expression
案例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 可写函数说明
sum = lambda arg1, arg2: arg1 + arg2
# 调用sum函数
print("相加后的值为 : ", sum( 10, 20 ))
3.概述pandas数据合并及数据映射的几种方法。
- 数据合并:concat()/append()/merge()/join()
- 数据映射:apply()/map()/applymap()
concat()
我们可以通过DataFrame或Series类型的concat方法,来进行连接操作,连接时,会根据索引进行对齐。
- axis:指定连接轴,默认为0(上下)。【axis=0/1】
- join:指定连接方式,默认为外连接。【join='outer':并集,join='inner':交集】
- keys:可以用来区分不同的数据组。形成层级索引【这个稍微难理解一点】
- join_axes:指定连接结果集中保留的索引。默认全部保留【如:join_axes=[df1.columns]】
- ignore_index:忽略原来连接的索引,创建新的整数序列索引,默认为False。【ignore_index=True/False】
- sort:concat之后,是否按照列索引排序,sort=True/False
import numpy as np
import pandas as pd
df1=pd.DataFrame({"date":[2015,2016,2017,2018,2019],"x1":[2000,3000,5000,8000,10000],"x2":[np.nan,"d","d","c","c"]})
df2=pd.DataFrame({'date':[2017,2018,2019,2020],"y1":[1000,2000,3000,2000]})
# display(df1,df2)
df3=pd.concat([df1,df2],keys=["df1","df2"])
display(df3)
#索引层级索引元素时,先外再内
df3.loc["df2",3].loc["y1"]
append()
在对行进行连接时,也可以使用Series或DataFrame的append方法。append是concat的简略形式,只不过只能在axis=0上进行合并。
import numpy as np
import pandas as pd
df1=pd.DataFrame({"date":[2015,2016,2017,2018,2019],"x1":[2000,3000,5000,8000,10000],"x2":[np.nan,"d","d","c","c"]})
df2=pd.DataFrame({'date':[2017,2018,2019,2020],"y1":[1000,2000,3000,2000]})
# display(df1,df2)
df3=df1.append(df2)
display(df3)
merge()
通过pandas或DataFrame的merge方法,可以进行两个DataFrame的连接,这种连接类似于SQL中对两张表进行的join连接。
- how:指定连接方式。可以是inner, outer, left, right,默认为inner。
- on 指定连接使用的列(该列必须同时出现在两个DataFrame中),默认使用两个DataFrame中的所有同名列进行连接。
- left_on / right_on:指定左右DataFrame中连接所使用的列。
- left_index / right_index:是否将左边(右边)DataFrame中的索引作为连接列,默认为False。
- suffixes:当两个DataFrame列名相同时,指定每个列名的后缀(用来区分),默认为x与y。
df1=pd.DataFrame({"date":[2015,2016,2017,2018,2019],"x1":[2000,3000,5000,8000,10000],"x2":[np.nan,"d","d","c","c"]})
df2=pd.DataFrame({'date':[2017,2018,2019,2020],"y1":[1000,2000,3000,2000]})
# display(df1,df2)
df3=df1.merge(df2,how='left',on="date")
display(df3)
join()
与merge方法类似,但是默认使用索引进行连接。
- 参数
- how:指定连接方式。可以是inner, outer, left, right,默认为left。
- on:设置当前DataFrame对象使用哪个列与参数对象的索引进行连接。
- lsuffix / rsuffix:当两个DataFrame列名相同时,指定每个列名的后缀(用来区分),如果不指定,列名相同会产生错误。
- join()和merge的异同
join与merge类似,都是进行两张表的连接。
merge默认进行的内连接(inner),join默认进行的左外连接(left)。
当出现同名字段(列索引)时,merge可以自动补后缀(_x, _y),但是join不会自动补后缀,而是会产生错误。
merge默认使用同名的列进行等值连接。join默认使用左右两表的索引进行连接。
merge中on参数,指定两张表中共同的字段,而join中on参数,仅指定左表中的字段(右表依然使用索引)。
merge与join侧重点不同,merge侧重的是使用字段进行连接,而join侧重的是使用索引进行连接。
df1=pd.DataFrame({"date":[2015,2016,2017,2018,2019],"x1":[2000,3000,5000,8000,10000],"x2":[np.nan,"d","d","c","c"]})
df2=pd.DataFrame({'date':[2017,2018,2019,2020],"y1":[1000,2000,3000,2000]})
# display(df1,df2)
df3=df1.join(df2,how='left',lsuffix='_x',rsuffix='_y')#根据索引对齐
display(df3)
应用 apply、map、applymap映射转换
Series与DataFrame对象可以进行行(列)或元素级别的映射转换操作:
- 对于Series,可调用apply或map方法。
- 对于DataFrame,可调用apply或applymap方法。
说明:
- apply:通过函数实现映射转换。【Series传递元素,DataFrame传递行或列。】
- map:对当前Series的值进行映射转换。参数可以是一个Series,一个字典或者是一个函数。
- applymap:通过函数实现元素级的映射转换。
Series的s.apply(function)转换
import numpy as np
import pandas as pd
#对于Series,依次传递每一个元素。
# 函数的参数只能一个,函数的返回值,用来表示处理的结果。
def fx(x): #定义一个函数
return 2*x+3
s = pd.Series([0,2,4])
s1 = s.apply(fx) #将Series中的每一个元素应用到函数中
display(s1)
# 对于非常简单的函数,我们可以使用lambda来实现。
s2 = s.apply(lambda x: x * 2 + 3) #应用于匿名函数
display(s2)
Series的s.map(map_series)
# 参数可以是Series,则根据Series的index来进行映射,获取结果值。
s = pd.Series([2, 3, 4])
map_series = pd.Series(["a", "b", "c", "e"],
index=[1,2,3,4])
s1 = s.map(map_series)
display(s1)
DataFrame调用apply,列级别的转换。df[[0, 1,...]].apply(function)
df = pd.read_excel(r"D:\Case_data/data01.xlsx",encoding="utf-8")
display(df)
# 自行求均值。
df2 = df[["资产(万)", "房产" ,"房产"]].apply(lambda x: x.mean())
display(df2)
def fx(x):
return x.mean()
df3 = df[["资产(万)", "房产" ,"房产"]].apply(fx)
display(df3)
DtaFrame调用applymap:通过函数实现元素级的映射转换
# 参数为一个函数,DataFrame中的每个元素都会调用一次该函数
# (将元素传递给该函数),获得一个映射的结果(函数的返回值)。
# applymap函数是一个元素级的映射,类似Series的map函数。
df = pd.read_excel(r"D:\Case_data/data01.xlsx",encoding="utf-8")
display(df)
df1 = df[["资产(万)"]].applymap(lambda x: x + 1000)
def fx(x):
y = x+1000
return y
df2 = df[["资产(万)"]].applymap(fx)
df3 = df[["资产(万)"]].apply(fx)
df4 = df["资产(万)"]*1+1000
display(df1,df2,df3,df4) #df1 == df2 == df3 == df4
4.简要说明用python做数据清洗时的流程及实现方法
数据清洗主要包含以下几方面内容:
- 处理缺失值
- 处理重复值
- 其他异常处理(离散值、错误值等)
python的Pandas库中,会将float类型的nan与None视为缺失值,我们可以通过如下方法来检测和处理缺失值:
处理缺失值
发现缺失值[info()/isnull()/notnull()]-丢弃缺失值[dropna()]/填充缺失值[fillna()]
- 案例数据
# 案例数据
import numpy as np
import pandas as pd
df = pd.read_excel(r"D:\Case_data/data01.xlsx",encoding="utf-8")
display(df)
- 发现缺失值
#发现缺失值
print("行列数:",df.shape)
# 按照列来检测缺失值,首先可以调用info方法进行整体查看。
# info方法可以显示DataFrame中每列的相关信息。
print(df.info())
#判断空值的情况
print(df.isnull().any() ,"\n") #按列检查每列是否有至少一个空
print(df.iloc[:,3:4].isnull().any() ,"\n") #检查指定列是否有至少一个空
print(df.notnull().all() ,"\n") #按列检查每列是否全部不为空
print(df.iloc[:,3:4].notnull().all() ,"\n") #按列检查指定列是否全部不为空
- 丢弃缺失值dropna(): df.dropna(axis=0/1,inplace=True/False,how='any' / how='all' / thresh=n)
- 参数:
- axis:指定丢弃行或者丢弃列(默认为丢弃行axis = 0)。axis=0 / axis=1
- inplace:指定是否就地修改,默认为False。是否就地操作
- how:指定dropna丢弃缺失值的行为,默认为any(只要存在就删除)。all (该行(列)全部为空才删除)/ any
- thresh:当非空数值达到该值时,保留数据,否则删除。如 thresh = 3,弥补how的不足(与how不同时使用)
#丢弃空值,使用dropna。
df1 = df.dropna() #默认<=>df2,# 这个行为表示:把df中的 有缺失字段值的任意一行都删掉,但不使用就地删除
# <=> df2 = df.dropna(axis=0,inplace=False,how='any')
print(df1.info() ,"\n") #处理后df1已经删除了有空值的行
print(df.info()) #由于inplace=False,所以df不变,后续继续处理和运算使用df1
- 填充缺失值fillna(): df.fillna(value / method ='ffill' [,limit=n] / method='bfill' [,limit=n] ,[inplace=True/False])
- 参数:
- value:填充所使用的值。固定值填充,支持直接输入值,支持字典,支持Series,需要注意的是字典的key值,Series的index要与df的列名称对应。
- method:指定前值(上一个有效值)填充(pad / ffill),还是后值(下一个有效值)填充(backfill / bfill)。
- limit:如果指定method,表示最大连续NaN的填充数量,如果没有指定method,则表示最大的NaN填充数量。
- inplace:指定是否就地修改,默认为False。
#向下填充
df1 = df.fillna(method="ffill",inplace=False)
display(df1)
#向上填充
df2 = df.fillna(method='bfill',inplace=False)
display(df2)
# limit参数。如果指定method,则表示最多连续填充。
# 如果没有指定method,则表示总共填充。
df3 = df.fillna(method="bfill", limit=1)
display(df3)
#填充值
df4 = df.fillna('空值')
display(df4)
重复值处理
发现重复值[duplicated()] -- 删除重复值[drop_duplicates()]
- 发现重复值duplicated():
r = df[df.duplicated( [subset=[0,1,...],keep='first'/'last'/False)] )] display(r.sort_values([1,0,...], axis=0))
- 参数说明:
- subset:指定依据哪些列判断是否重复,默认为所有列。
- keep:指定记录被标记为重复(True)的规则。默认为first
#指定标记重复记录的规则
result = df[df.duplicated(['姓名','资产(万)'],keep=False)]
# <==> result = df[df.duplicated(subset=['姓名','资产(万)'],keep=False)] #自定义用于判断重复的列
display(result.sort_values(['姓名','资产(万)'], axis=0)) #排序
- 删除重复值drop_duplicates():
df.drop_duplicates([subset=[0,1,...], keep='first'/'last',inplace=Ture/False])
- 参数说明:
- subset:指定依据哪些列判断是否重复,默认为所有列。
- keep:指定记录删除(或保留)的规则。默认为first,所以一般不要再自行指定keep啦。
- inplace:指定是否就地修改,默认为False。
- #如果想了解关于当前这个方法的更多参数。怎么办?
df.drop_duplicates # 按组合键:shift+tab建 4次
r = df[df.duplicated(subset=['姓名','资产(万)'])]
display(r) #获取重复值
df1 = df.drop_duplicates(subset=['姓名','资产(万)'],keep='first',inplace=False)
display(df1) #删除重复制后的结果
其他异常处理(离散值、错误值等)
可以通过DataFrame对象的describe方法查看数据的统计信息。不同类型的列,统计信息也不太相同。
- (1)、获取统计信息
- df.describe() 获取数值列统计信息
- df[[0,1,2]].describe() 获取指定的非数值列统计信息
- df.shape 获取行列数量
- df.info() 获取缺失值信息
df.describe().round(2)
- (2)、画图检验。如散点图、箱型图
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt #最常用的绘图库
mpl.rcParams["font.family"]="SimHei" #使用支持的黑体中文字体
mpl.rcParams["axes.unicode_minus"]=False # 用来正常显示负数 "-"
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签
df["x"]=list(df.index.values)
df.plot(kind="scatter",x = "x",y="现金")
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt #最常用的绘图库
mpl.rcParams["font.family"]="SimHei" #使用支持的黑体中文字体
mpl.rcParams["axes.unicode_minus"]=False # 用来正常显示负数 "-"
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签
# df.plot.box(title="Consumer spending in each country", vert=False)
df["现金"].plot.box(title="现金箱线图")
plt.grid(linestyle="--", alpha=0.3)
plt.show()
- (3)、根据统计信息再做相应的处理。如错误值的替换或者删除;离散值的删除。
- replace替换:df.replace(to_replace,regex,......)
- 索引替换:df["房产1"][df["房产1"].astype("str") == "0"]="否"
- 映射替换
- 元素替换
5.用python随机生成某月1-30号每天的销售额数据,并按照周聚合,同时用任意python作图库做图。
- 构造随机数
import random
import datetime
import time
def getBetweenDay(begin_date,end_date):
date_list = []
begin_date = datetime.datetime.strptime(begin_date, "%Y-%m-%d")
end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d")
while begin_date < end_date:
date_str = begin_date.strftime("%Y-%m-%d")
date_list.append(date_str)
begin_date += datetime.timedelta(days=1)
return date_list
getBetweenDay("2020-10-01","2020-11-01")
a = getBetweenDay("2020-10-01","2020-11-01")
b = len(getBetweenDay("2020-10-01","2020-11-01"))
c = list([random.randrange(100,150) for i in range(b)])
d= pd.DataFrame()
d["日期"] = a
d["交易额(万)"] = c
display(d.tail(5))
# 日期转化
print(d.dtypes)# 查看数据类型
d["日期"]=pd.to_datetime(d["日期"],errors="coerce")
print(d["日期"].dtypes,"\n------------")
d["第n周"]=d["日期"].dt.week
display(d.head(5))
gd= d[["第n周","交易额(万)"]].groupby(
["第n周"]).agg(
{"交易额(万)":["count","sum","mean"]})
gd.columns=["天数","合计金额","日均金额"]
gd["第n周"]= list(gd.index.values)
display(gd.round(2))
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt #最常用的绘图库
mpl.rcParams["font.family"]="SimHei" #使用支持的黑体中文字体
mpl.rcParams["axes.unicode_minus"]=False # 用来正常显示负数 "-"
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签
x, y, z = gd["周"], gd["合计金额"],gd["日均金额"]
axes1=plt.subplot(2,1,1)
axes1.bar(x,y,alpha=0.5,color="c")
plt.title("周-合计金额")
axes2=plt.subplot(2,1,2)
axes2.plot(x,z,alpha=0.5,color="c")
plt.title("周-日均金额")
# #添加标签值
for x,y, z in zip(x,y, z): # zip是将X,z分别传到x,y中,传两个
axes1.text(x, y + 0.5, '%.1f' % y, ha='center', va='bottom') # ha,va规定坐标表示的点,默认左下
axes2.text(x, z + 0.5, '%.1f' % z, ha='center', va='bottom') # ha,va规定坐标表示的点,默认左下
plt.show()
以上便是5道关于数据分析师对python的基本使用的5道面试题了。这5个题目不管是面试问答或者是笔试做题中最常涉及的5个基本面。希望需要的小伙伴们收藏并认真总结,同时别忘记关注点赞加分享。
扫
码
关
注
更多数据分析与运营知识
干货在此,随时学习!