pandas(综合测试)

  课程资料《pandas数据处理与分析》github地址讲解视频习题参考答案pandas官网
传送门:

一、补充习题

Ex1:NumPy的向量化运算

  1. 给定一个正整数列表,请找出缺失的最小正整数。
arr = np.array([2,3,4])
get_miss(arr)
1
arr = np.array([6,3,5,1,2])
get_miss(arr)
4
arr = np.array([5,2,1,3,4])
get_miss(arr)
6
# 思路:排序后diff做差,找到差值为2的索引对应的元素减一就是,多个值取最小。
def get_miss(n):
    s=pd.Series(n).sort_values()
    if s[0]!=1:
        return 1
    elif s.diff().dropna().sum()==len(s)-1:
        return len(s)+1
    else:
        miss_index=s.diff()[s.diff().values==2].index
        return (n[miss_index]-1).min()  
  1. 设计一个生成二维NumPy数组的函数get_res(),其输入为正整数n,返回的数组构造方式如下:第1行填入1个1,第2行在上一行填入位置的下一列连续填入2个2,第3行在第二行最后一个填入位置的下一列连续填入3个3,…,第n行在第n-1行最后一个填入位置的下一列连续填入n个n。
n = 4
get_res(n)
array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 2., 2., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 3., 3., 3., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 4., 4., 4., 4.]])

本来想生成没有0的list[[i]*i for i in range(1,n+1,1)求索引来知道每个数前后填多少0,但是还得展平、求索引,太麻烦。还是老老实实计算前后填充0的个数好了:

# 生成numpy格式只求求sum,懒得写循环求和
def sum_list(n):
	return np.array([i for i in range(1,n+1,1)]).sum() if n!=0 else 0
	
def get_res(n):
    ls=[]
    le=sum_list(n)
    for i in range(1,n+1,1):
        lt=[0]*sum_list(i-1)+[i]*i+[0]*(le-sum_list(i-1)-i)
        ls.append(lt)
    return np.array(ls)
get_res(5)

array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5]])
  1. 点 A 初始位置在数轴原点处,现进行n步简单随机游走,即每一步以等概率向左或向右移动长度为1的距离,记该点最终的位置为 S n S_n Sn ,则可以证明:
    在这里插入图片描述
my_list = [-1,1]
def test(n):
    ls=np.random.choice(my_list, 100, p=[0.5,0.5]) # choice函数随机取样
    return int(np.fabs(ls.sum())) # ls的和就是最终点的位置,返回位置s_n的绝对值
def ponits(n):
    lg_1000=[]
    for j in range(1000): # 运行1000次试验
        ls_100=[]
        for i in range(100): # 循环100次取均值求E|s_n|
            sn=test(n)
            ls_100.append(sn)
        esn=np.array(ls_100).mean() # 100次sn均值
        result=esn/np.sqrt(n)-np.sqrt(2/np.pi)
        lg_1000.append(result)
    return np.array(lg_1000)

anwser=ponits(5000)
anwser.mean(),np.quantile(anwser,0.05),np.quantile(anwser,0.95) # 为啥结果不是接近0呢
(-0.685692170472683, -0.6997381395741726, -0.6717367110391853)
  1. 在二维平面上有n个点,每个点具有k维特征,点的坐标数据记录在node_xy中,点的特征数据记录在node_fea中。现要计算所有点的相关矩阵S,点a和点b的相关系数定义如下:
    在这里插入图片描述
n, k = 1000, 10
node_xy = np.random.rand(n, 2)
node_fea = np.random.rand(n, k)
get_S(node_xy, node_fea)
  • 计算 σ a b \sigma _{ab} σab:
def sigma(a,b):
    return a@b/(np.linalg.norm(a)*np.linalg.norm(b))
  • 计算 λ a b \lambda _{ab} λab
    计算出每个点和其它点的距离表格,后面再查表,不知道是不是快一点。
# 计算两点欧氏距离用np.linalg.norm(a-b)
# 计算出每个点和其它点的距离表格
ls,le=[],len(node_xy)
for i in range(le):
    for j in range(0,le):
        if i!=j:
            ls.append(np.linalg.norm(node_xy[i]-node_xy[j]))
        else:
            continue
df_all=pd.DataFrame(np.array(ls).reshape(le,-1))
new_cloumns=['点'+str(i) for i in range(1,le,1)]
df.columns=new_cloumns
df
		点1234
0	0.891908	0.259182	0.528596	0.302012
1	0.891908	0.632727	0.602179	0.939268
2	0.259182	0.632727	0.374223	0.396821
3	0.528596	0.602179	0.374223	0.399266
4	0.302012	0.939268	0.396821	0.399266

但是貌似计算量还是一样的,而且排名、查表写起来很麻烦,直接莽吧。就是知道了还有排名函数rank。
算了,还是不会做,放弃了

Ex2:统计学生的成绩情况

在data/supplement/ex2目录下存放了某校高三第一学期的学生成绩情况,包含16次周测成绩、期中考试成绩和期末考试成绩,科目一栏的成绩表示学生选课的成绩。所有的表中,相同的行表示的是同一位同学。请完成以下练习:

df = pd.read_csv('data/supplement/ex2/第1次周测成绩.csv')

df.head()
Out[5]: 
   班级   姓名   选科   语文  数学   英语  科目
0   1    吴刚    地理   93   95    82    69
1   1    卢楠    物理  108   77    90    94
2   1    唐秀兰  历史   88   72    95    85
3   1    张刚    化学   85   88   102    76
4   1    姜洋    历史  104   99    84    86
  1. 该校高三年级中是否存在姓名相同的学生?

  2. 在第一次周测中,请求出每个班级选修物理或化学同学的语数英总分的平均值。哪个班级最高?

  3. 学生在该学期的总评计算方式是各次考试总分的加权平均值,其中周测成绩权重为50%(每次测验权重相等,即3.125%),期中权重为20%,期末权重为30%。请结合nlargest函数找出年级中总评前十的同学。

  4. 请统计1班到8班文理科(物化生为理科,政史地为文科)期末考试总分前5的学生,结果格式如下,括号内的为选科分数:

pd.DataFrame(
    {
        "1班(文)": ["王大锤:历史(102)"]+["..."]* 4,
        "1班(理)": ["..."]* 5,
        "2班(文)": ["..."]* 5,
        "...": ["..."]* 5,
        "8班(理)": ["..."]* 5,
    }
) # 王大锤:历史(102)只是举个例子,表示结果字符串需要按照这个格式来写

Out[6]: 
         1班(文) 1班(理) 2班(文)  ... 8班(理)
0  王大锤:历史(102...   ...  ...   ...
1          ...   ...   ...  ...   ...
2          ...   ...   ...  ...   ...
3          ...   ...   ...  ...   ...
4          ...   ...   ...  ...   ...
  1. 学生成绩的稳定性可以用每次考试在全年级相同选科学生中的总分排名标准差来度量,请计算每个班级的各科学生成绩稳定性的均值,结果格式如下:
pd.DataFrame(
    np.random.rand(11, 6),
    index=pd.Index(range(1, 12), name="班级"),
    columns=pd.Index(
        ["物理", "化学", "生物", "历史", "地理", "政治"],
        name="选科",
    )
)

Out[7]: 
选科        物理        化学        生物        历史        地理        政治
班级                                                            
1   0.461479  0.780529  0.118274  0.639921  0.143353  0.944669
2   0.521848  0.414662  0.264556  0.774234  0.456150  0.568434
3   0.018790  0.617635  0.612096  0.616934  0.943748  0.681820
4   0.359508  0.437032  0.697631  0.060225  0.666767  0.670638
5   0.210383  0.128926  0.315428  0.363711  0.570197  0.438602
6   0.988374  0.102045  0.208877  0.161310  0.653108  0.253292
7   0.466311  0.244426  0.158970  0.110375  0.656330  0.138183
8   0.196582  0.368725  0.820993  0.097101  0.837945  0.096098
9   0.976459  0.468651  0.976761  0.604846  0.739264  0.039188
10  0.282807  0.120197  0.296140  0.118728  0.317983  0.414263
11  0.064147  0.692472  0.566601  0.265389  0.523248  0.093941
  1. 该校高三年级中是否存在姓名相同的学生?
#df['姓名'].value_counts().sort_values() # 最大值还是1,没有重名
len(df.drop_duplicates(subset=['姓名'] ))==len(df) # 为True没有重名
  1. 在第一次周测中,请求出每个班级选修物理或化学同学的语数英总分的平均值。哪个班级最高?
df.loc[df['选科'].isin(['物理','化学'])].groupby(df['班级'])[['语文','数学','英语']].\
            mean().sum(1).sort_values(ascending=False).head()/3
班级
2     93.939394
1     91.575758
6     90.964912
7     90.272727
9     90.023810
dtype: float64
  1. 学生在该学期的总评计算方式是各次考试总分的加权平均值,其中周测成绩权重为50%(每次测验权重相等,即3.125%),期中权重为20%,期末权重为30%。请结合nlargest函数找出年级中总评前十的同学。
import os
data_dir='./data/supplement/ex2'
df_16=pd.DataFrame(columns=['班级', '姓名', '选科', '语文', '数学', '英语', '科目'])
for file_name in os.listdir(data_dir):    
    if file_name=='期中考试成绩.csv':
        df_mid=pd.read_csv(os.path.join(data_dir,file_name)).set_index('姓名').sort_index()
    elif file_name=='期末考试成绩.csv':
        df_end=pd.read_csv(os.path.join(data_dir,file_name)).set_index('姓名').sort_index()
    else:
        df_week=pd.read_csv(os.path.join(data_dir,file_name))
        df_16=pd.concat([df_16,df_week],axis=0)  

# 16次周测验的总成绩平均值
score_week=df_16.groupby(df['姓名'])[['语文','数学','英语','科目']].sum().sum(1).sort_index()/16

姓名
丁帅     387.5000
丁斌     404.8750
丁燕     387.4375
万云     395.8750
万志强    399.7500
         ...   
龙晨     390.3750
龙秀荣    393.5625
龙鑫     404.1875
龙雪梅    393.1250
龚建华    391.1250
Length: 896, dtype: float64
score=df_mid[['语文','数学','英语','科目']].sum(1)*0.2+\
      df_end[['语文','数学','英语','科目']].sum(1)*0.3+score_week*0.5
score.sort_values(ascending=False).index[:10]

Index(['王想', '黄萍', '黄文', '黎玉', '王淑英', '慕阳', '杨凤兰', '张欢', '吕雪', '孙桂珍'], dtype='object', name='姓名')
  1. 请统计1班到8班文理科(物化生为理科,政史地为文科)期末考试总分前5的学生,结果格式如下,括号内的为选科分数
df8=df_end.loc[df_end['班级']<9].reset_index() # 选出前8个班的同学
# 根据班级、姓名、文理科分组,计算总分
df8=df8.groupby([df8['班级'],df8['选科'].isin\
                        (['物理','化学','生物']),df8['姓名']])[['语文','数学','英语','科目']].sum(1).sum(1) 
df8=pd.DataFrame(df8,columns=['总分']).reset_index()
df8

	班级 选科	    姓名		总分
0	1	False	任兰英	351
1	1	False	余峰	    367
2	1	False	刘丽	    390
3	1	False	刘婷婷	414
4	1	False	刘桂荣	394
...	...	...	...	...
676	8	True	陈玲		351
677	8	True	高莉		381
678	8	True	黄利		382
679	8	True	黄斌		423
680	8	True	黎想		430
# 定义组内排序函数
def sort(s):
    return s.sort_values(['总分'],ascending=False)[:5]
# 根据班级、文理科分组排序取前5名
df_top5=df8.groupby([df8['班级'],df8['选科']])[['姓名','总分']].agg(sort).reset_index()
del df_top5['level_2'] # 重设索引时多了一列之前的索引,将其去掉
df_top5.head()

	班级	选科		姓名	    总分
0	1	False	秦利		435
1	1	False	王雷		415
2	1	False	刘婷婷	414
3	1	False	唐秀兰	411
4	1	False	龙晨		401
df_top5=df_top5.merge(df_end,on=['姓名','班级'],how='left') # 合并之前的表拿到选科和选科成绩
# 更改格式方便后面合并列
df_top5['班级']=df_top5['班级'].apply(lambda x : str(x)+'班')
df_top5['选科_x']=df_top5['选科_x'].apply(lambda x: '(理)' if x else '(文)')
df_top5['科目']=df_top5['科目'].apply(lambda x :'('+str(x)+')')

df_top5.eval('班级=班级+选科_x',inplace=True)
df_top5.eval('科目=选科_y+科目',inplace=True)
df_top5=df_top5[['班级','姓名','科目']]
df_top5['姓名']=df_top5['姓名'].apply(lambda x : str(x)+':')
df_top5.eval('姓名=姓名+科目',inplace=True)
del df_top5['科目']
df_top5 # 到这一步改不了横表了,不会做啊

		班级		姓名
0	1班(文)	秦利:地理(1161	1班(文)	王雷:地理(1162	1班(文)	刘婷婷:地理(1153	1班(文)	唐秀兰:历史(1154	1班(文)	龙晨:地理(106...	...	...
75	8班(理)	王想:物理(11576	8班(理)	刘娜:化学(10277	8班(理)	黎想:化学(11878	8班(理)	严琳:化学(12579	8班(理)	张桂香:物理(124
  1. 学生成绩的稳定性可以用每次考试在全年级相同选科学生中的总分排名标准差来度量,请计算每个班级的各科学生成绩稳定性的均值。
# 之前的df_mid和df_end索引都是姓名,连接时要重置索引
df_all=pd.concat([df_16,df_mid.reset_index(),df_end.reset_index()],axis=0).reset_index()
df_all.eval('总分=语文+数学+英语+科目',inplace=True)
# 将index设置为考试的次数,比如第一次、第二次......第18次
# 列表ls是1到18重复896次后展平
ls=np.array([[i]*896 for i in range(1,19,1)]).flatten()
df_all.loc[df_all.index,'index']=ls
df_all # index为第几次考试

 index	班级	姓名		选科	语文	数学	英语	科目	总分
0	1	1	吴刚		地理	102	84	106	104	396
1	1	1	卢楠		物理	78	88	87	79	332
2	1	1	唐秀兰	历史	106	86	111	112	415
3	1	1	张刚		化学	97	77	80	113	367
4	1	1	姜洋		历史	101	89	93	105	388
def sort(s):
    return s.sort_values(['总分'],ascending=False)
# 每次考试各个选科根据总分排序
df_all=df_all.groupby([df_all['index'],df_all['选科']])[['班级','姓名','总分']].agg(sort).reset_index()
size=df_all.groupby([df_all['index'],df_all['选科']])['level_2'].size() # 得到每个组别的元素个数,也就是每组排序长度

sort_index=np.array([[i for i in range(1,j+1,1)] for j in size.values]).flatten() # 不定长序列无法展平
lg=[]
for i in sort_index:
    for j in i:
        lg.append(j)

df_all.level_2=lg
df_all=df_all.rename(columns={'level_2':'排名'})
df_all # 得到每次考试每个学科排名情况

	 index	选科	  排名	班级	 姓名	总分
0		1	化学	  1		3	杨桂荣	447
1		1	化学	  2		8	狄琳		443
2		1	化学	  3		11	夏刚		441
3		1	化学	  4		4	吴淑兰	437
4		1	化学	  5		6	韩柳		436
...	...	...	...	...	...	...
16123	18	生物	 162	6	沈涛		332
16124	18	生物	 163	4	王浩		331
16125	18	生物	 164	5	萧秀云	323
16126	18	生物	 165	6	沈欣		317
16127	18	生物	 166	2	谷静		303
result=df_all.groupby([df_all['选科'],df_all['姓名']])[['班级','排名']].std() # 计算排名标准差
result['班级']=df_mid.sort_values(['选科','姓名']).reset_index()['班级'] # 结果加入班级字段
anwser=result.groupby([result['班级'],result['选科']])['排名'].mean() # 对班级选科分组求std
anwser=pd.DataFrame(anwser)
anwser.unstack(1) # 转换格式

在这里插入图片描述

Ex3:统计商品的审核情况

在data/supplement/ex3中存放了两个有关商品审核的信息表,“商品信息.csv”中记录了每个商品的ID号,唯一的识别码以及商品所属的类别,“申请与审核记录.csv”中记录了每个商品的审核信息。已知商品的审核流程如下:由申请人发起商品审核的申请,然后由审核人审核,审核的结果包括通过与不通过两种情况,若商品不通过审核则可以由另一位申请人再次发起申请,直到商品的审核通过。

df_info = pd.read_csv('data/supplement/ex3/商品信息.csv')

df_info.head()
Out[9]: 
       ID号    识别码  类别
0  ID 000001  CRtXJUK  T1
1  ID 000002  RGSxifC  Q1
2  ID 000003  AboduTp  S1
3  ID 000004  zlpUeMl  S2
4  ID 000005  IVQqhIK  S3

df_record = pd.read_csv('data/supplement/ex3/申请与审核记录.csv')

df_record.head()
Out[11]: 
       ID号       申请人      申请时间       审核人      审核时间    结果
0  ID 000001  \#+3((52\{  2020-04-19  ~1=6\*183|  2020-05-03  未通过
1  ID 000001  8@75[1|2\*  2020-05-10  15![3\({59  2020-07-17  未通过
2  ID 000001  }!7)(#^0*7  2020-07-28  3`}04}%@75  2020-08-23   通过
3  ID 000002  |*{20#9|}5  2020-01-05  ={`8]03*4+  2020-03-09  未通过
4  ID 000002  4~6%)455`[  2020-03-14  =$-36[)|8]  2020-04-21  未通过
  • 有多少商品最终通过审核?
  • 各类别商品的通过率分别为多少?
  • 对于类别为“T1”且最终状态为通过的商品,平均审核次数为多少?
  • 是否存在商品在上一次审核未完成时就提交了下一次审核申请?
  • 请对所有审核通过的商品统计第一位申请人和最后一位审核人的信息,返回格式如下:
pd.DataFrame(
    {
        "ID号": ["ID 000001"]+["..."]*3,
        "类别":["T1"]+["..."]*3,
        "申请人":["\#+3((52\{"]+["..."]*3,
        "审核人":["3`}04}%@75"]+["..."]*3
    },
    index=[1,2,3,"..."]
)

Out[12]: 
           ID号   类别         申请人         审核人
1    ID 000001   T1  \#+3((52\{  3`}04}%@75
2          ...  ...         ...         ...
3          ...  ...         ...         ...
...        ...  ...         ...         ...
  1. 有多少商品最终通过审核?
df_record['结果'].value_counts() # 10848
未通过    136652
通过      10848
Name: 结果, dtype: int64

或者是:

# 计算结果为通过和ID的唯一组合数,更严谨的写法,防止一个ID通过两次
len(df_record[df_record.结果=='通过'].groupby(['ID号','结果']). groups)
  1. 各类别商品的通过率分别为多少?
df_record合并加入类别和识别码字段
df=df_record.merge(df_info,on='ID号',how='left')
df.groupby(['类别','结果'])['结果'].count() # 计算每个类别是否通过的个数
类别  结果 
Q1  未通过    19153
    通过      1494
Q2  未通过    20010
    通过      1613
S1  未通过    19552
    通过      1538
S2  未通过    19162
    通过      1548
S3  未通过    19529
    通过      1582
T1  未通过    19324
    通过      1509
T2  未通过    19922
    通过      1564
Name: 结果, dtype: int64
# to_frame()将Series转为DataFrame结构,将类别从转到列,这样就好计算了
# 再去除列的外层索引,index名丢失,重命名为'结果'。
res=df.groupby(['类别','结果'])['结果'].count().\
			  to_frame().unstack(0).droplevel(0,axis=1).rename_axis('结果')
res
类别		Q1		Q2		S1		S2		S3		T1		T2
结果							
未通过	19153	20010	19552	19162	19529	19324	19922
通过		1494	1613	1538	1548	1582	1509	1564

res[res.index=='通过'].values/res.sum().values # 这样无法转为百分数,还得改
array([[0.07235918, 0.07459649, 0.07292556, 0.0747465 , 0.07493724,
        0.07243316, 0.07279159]])
res=(res[res.index=='通过']/res.sum()).stack(0).apply(lambda x: format(x, '.2%')) .to_frame()
res.columns=['通过率']
res.reset_index()

	结果	类别	通过率
0	通过	Q1	7.24%
1	通过	Q2	7.46%
2	通过	S1	7.29%
3	通过	S2	7.47%
4	通过	S3	7.49%
5	通过	T1	7.24%
6	通过	T2	7.28%
  1. 对于类别为“T1”且最终状态为通过的商品,平均审核次数为多少?
# 获取所以T1类里面通过审核的商品ID
ids=df.loc[(df.类别=='T1')&(df.结果=='通过'),'ID号']
df[df['ID号'].isin(ids)].groupby('ID号')['结果'].count().mean()

5.547382372432074
  1. 是否存在商品在上一次审核未完成时就提交了下一次审核申请?
df.申请时间=pd.to_datetime(df.申请时间) # 转为时间序列
df.审核时间=pd.to_datetime(df.审核时间)
# 申请时间上移一位
df.申请时间[:-1]=df.申请时间[1:]
df.eval('时间差=审核时间-申请时间',inplace=True)
# 获取每件商品在表格在切换的位置,这个位置计算的时间差是两种商品的时间差,不应该计入
df['index']=df.index
del_ids=df.groupby(df['ID号'])['index'].max().values
del_ids,len(del_ids)

array([     2,      7,     10, ..., 147488, 147493, 147499], dtype=int64)
# 计算非切换位置时间差是否大于0的真假矩阵的唯一值统计
anwser=df.loc[~df['index'].isin(del_ids)]['时间差'].dt.days<0
anwser.value_counts() # 所以是有3182件商品没审核就提交的

True     117486
False      3182
Name: 时间差, dtype: int64
# 看看没有过滤切换位置的情况
(df['时间差'].dt.days<0).value_counts() 
True     117524
False     29976
Name: 时间差, dtype: int64

下面试着找到这3182件商品,没有找到,醉了

n1=df.loc[(df['时间差'].dt.days>0)].index.values # 所有时间差大于0的商品的索引
n2=df.loc[~df['index'].isin(del_ids)]['index'].values # 不是切换位置的索引
inter=np.intersect1d(n1,n2) # numpy求二者的交集
array([], dtype=int64) # 没有交集.......

  最后我试了无数遍,发现漏了时间差=0的情况,即当天审核完当天提交。所以一开始上面判断条件应该用>0。怪不得我后面想找这3182件死活找不出来。

(df.loc[~df['index'].isin(del_ids)]['时间差'].dt.days==0).value_counts()
True     117486
False      3182
Name: 时间差, dtype: int64
(df.loc[~df['index'].isin(del_ids)]['时间差'].dt.days>0).value_counts()
False    120668
Name: 时间差, dtype: int64
  1. 请对所有审核通过的商品统计第一位申请人和最后一位审核人的信息,返回指定格式
id_pass=df.loc[(df.结果=='通过'),'ID号'] # 审核通过的商品ID号
df['index']=df.index.values # 加入一列为其index方便筛选

统计每件商品申请时间是否按顺序排列

td=df.groupby('ID号')['申请时间'].diff(1) # 根据ID号将各个商品分开统计申请时间,用diff做差
(td.dt.days<0).value_counts() # 统计是否有差小于0,也就是申请时间是否都是按顺序来的
False    147500
Name: 申请时间, dtype: int64 

每件商品的申请时间都是按顺序来的,所以index最小的对应的就是第一个申请的人

app_ids=df[df['ID号'].isin(id_pass)].groupby('ID号')['index'].min().values
df1=df.loc[df['index'].isin(app_ids),['ID号','申请人']] 
df1

			ID号	申请人
0		ID 000001	\#+3((52\{
17		ID 000005	=_@@9(2|#|
27		ID 000008	3~2#9`*~#8
56		ID 000013	78!#-24|)&
85		ID 000019	+_0!]*8!]$
...	...	...
147420	ID 026819	\%\=4$9@+-
147442	ID 026823	}{**\(7&&(
147449	ID 026824	+5&%{#*`_`
147470	ID 026828	\##{~+^9!3
147480	ID 026830	@`=(2@03^0

统计每件商品审核时间是否按顺序排列

td2=df.groupby('ID号')['审核时间'].diff(1) # 根据ID号将各个商品分开统计申请时间,用diff做差
(td2.dt.days<0).value_counts() # 统计是否有差小于0,也就是申请时间是否都是按顺序来的

False    147500
Name: 审核时间, dtype: int64

每件商品的审核时间都是按顺序来的,所以index最大的对应的就是最后一个审核的人。因为按常理来说肯定是先申请后审核,而且通过之后不再申请。

Reviewer_ids=df[df['ID号'].isin(id_pass)].groupby('ID号')['index'].max().values
df2=df.loc[df['index'].isin(Reviewer_ids),['ID号','审核人']] 
df2

		ID号	审核人
2		ID 000001	3`}04}%@75
19		ID 000005	^7#10{&3^6
30		ID 000008	*}-5[$$]87
61		ID 000013	)`]({`6-52
88		ID 000019	{---]\43!@
...	...	...
147422	ID 026819	@5~@$=#3[]
147448	ID 026823	53~(\4|7(=
147455	ID 026824	012&*&$]}
147472	ID 026828	@`^=@!{0#@
147488	ID 026830	[_7\=*\(#8
df1.merge(df2,on='ID号',how='left')
df_all=df1.merge(df2,on='ID号',how='left')
df_all['类别']=df[df['ID号'].isin(id_pass)]['类别']
df_all.iloc[:,[0,3,1,2]] # 新增类别列在最后,用iloc拿到ID后面

	   		ID号   	类别	  申请人		审核人
0		ID 000001	T1	\#+3((52\{	3`}04}%@75
1		ID 000005	T1	=_@@9(2|#|	^7#10{&3^6
2		ID 000008	T1	3~2#9`*~#8	*}-5[$$]87
3		ID 000013	NaN	78!#-24|)&	)`]({`6-52
4		ID 000019	NaN	+_0!]*8!]$	{---]\43!@
...	...	...	...	...
10843	ID 026819	NaN	\%\=4$9@+-	@5~@$=#3[]
10844	ID 026823	NaN	}{**\(7&&(	53~(\4|7(=
10845	ID 026824	NaN	+5&%{#*`_`	012&*&$]}
10846	ID 026828	NaN	\##{~+^9!3	@`^=@!{0#@
10847	ID 026830	NaN	@`=(2@03^0	[_7\=*\(#8
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神洛华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值