pandas组内排序,并在每个分组内按序打上序号?
8 个回答
就在提出问题后的半个小时,网上的一位朋友给出了答案,在这里分享给大家。作为python的初学者,前辈的提点对于成长真的是很有帮助。
假设我已经建好了仅有前三列的dataframe,命名为My_Frame,那么解决方案如下:
My_Frame['sort_id'] = My_Frame['salary'].groupby(My_Frame['dep_id']).rank()
Pandas基础·第2篇 —— 如何用Pandas对DataFrame进行排序和统计?
目录
《Pandas1.x实例精解》新书抢先看!
【第1篇】利用Pandas操作DataFrame的列与行
排序列名称
在最初将数据集导入为DataFrame之后,首先要考虑的任务之一就是分析列的顺序。由于多数人的习惯是从左到右阅读文字资料,因此,列顺序会影响我们对数据的理解。如果有一个合理的列顺序,那么查找和解释信息要容易得多。
虽然Pandas没有标准的规则集来规定在数据集中应如何组织列,但是,最好的做法是制订一组你自己始终遵循的准则。如果你与一组分析师合作,并且需要共享大量的数据集,则尤其应该如此。
以下是对列进行排序的一般准则。
- 将每一列划分为分类列或连续列。
- 在分类列和连续列中,对公共列分组。
- 将最重要的列组放置于首位,然后放置分类列,最后放置连续列。
此秘笈将演示如何使用上述一般准则排序各列。需要说明的是,排序方法有很多种,只要方便你自己的应用即可。
实战操作
(1)读取movie数据集,然后扫描数据。
>>> movies = pd.read_csv("data/movie.csv")
>>> def shorten(col):
... return col.replace("facebook_likes", "fb").replace(
... "_for_reviews", ""
... )
>>> movies = movies.rename(columns=shorten)
(2)输出所有列名称,并扫描相似的分类列和连续列。
>>> movies.columns
Index(['color', 'director_name', 'num_critic', 'duration',
'director_fb', 'actor_3_fb', 'actor_2_name', 'actor_1_fb', 'gross',
'genres', 'actor_1_name', 'movie_title', 'num_voted_users',
'cast_ total_fb', 'actor_3_name', 'facenumber_in_poster',
'plot_keywords', 'movie_imdb_link', 'num_user', 'language', 'country',
'content_rating', 'budget', 'title_year', 'actor_2_fb', 'imdb_score',
'aspect_ratio', 'movie_fb'], dtype='object')
(3)这些列似乎没有什么逻辑顺序。我们可以将列名称以比较合理的方式组织到列表中,以遵循前面介绍的一般准则。
>>> cat_core = [
... "movie_title",
... "title_year",
... "content_rating",
... "genres",
... ]
>>> cat_people = [
... "director_name",
... "actor_1_name",
... "actor_2_name",
... "actor_3_name",
... ]
>>> cat_other = [
... "color",
... "country",
... "language",
... "plot_keywords",
... "movie_imdb_link",
... ]
>>> cont_fb = [
... "director_fb",
... "actor_1_fb",
... "actor_2_fb",
... "actor_3_fb",
... "cast_total_fb",
... "movie_fb",
... ]
>>> cont_finance = ["budget", "gross"]
>>> cont_num_reviews = [
... "num_voted_users",
... "num_user",
... "num_critic",
... ]
>>> cont_other = [
... "imdb_score",
... "duration",
... "aspect_ratio",
... "facenumber_in_poster",
... ]
(4)将所有列表连接在一起以获得最终的列顺序。另外,请确保此列表包含原始数据集中的所有列。
>>> new_col_order = (
... cat_core
... + cat_people
... + cat_other
... + cont_fb
... + cont_finance
... + cont_num_reviews
... + cont_other
... )
>>> set(movies.columns) == set(new_col_order)
True
(5)将包含新列顺序的列表传递给DataFrame的索引操作符,以对列进行重新排序。
>>> movies[new_col_order].head()
movie_title title_year ... aspect_ratio facenumber_in_poster
0 Avatar 2009.0 ... 1.78 0.0
1 Pirates ... 2007.0 ... 2.35 0.0
2 Spectre 2015.0 ... 2.35 1.0
3 The Dark... 2012.0 ... 2.35 0.0
4 Star War... NaN ... NaN 0.0
原理解释
分析人员可以使用包含特定列名称的列表从DataFrame中选择列的子集。例如,movies[['movie_title','director_name']]即可创建一个仅包含movie_title和director_name列的新DataFrame。按名称选择列是Pandas DataFrame的索引操作符的默认行为。
步骤(3)根据类型(分类或连续列)以及它们的数据相似程度,将所有列名称整齐地组织到单独的列表中。最重要的列(如电影的片名)位于第一位。
步骤(4)连接了所有列名称列表,并验证此新列表包含与原始列名称相同的确切值。Python数据集是无序的,而相等(==)语句则可以检查一个集合中的每个成员是否是另一个集合中的成员。手动排序此秘笈中的列容易受到人为错误的影响,因为我们很容易忘记新的列名称列表中的某一列。
步骤(5)通过将新的列顺序作为列表传递给索引操作符来完成重新排序。现在,这个新排序要比原来的排序合理得多。
扩展知识
除了前面提到的建议,还有其他排序列的准则。Hadley Wickham在有关规整数据 (tidy data)的开创性论文中建议将固定变量放在首位,然后放置测量变量。由于movie数据并非来自受控实验,因此在确定哪些变量是固定的和哪些变量是测量的方面都具有一定的灵活性。测量变量的良好候选者是我们希望预测的变量,如gross(票房收入)、budget(预算)或imdb_score(互联网电影资料库评分)等。以这种顺序,我们可以混合使用分类变量和连续变量。例如,在演员的姓名之后直接放置在Facebook平台上的喜欢/ 点赞数的列可能更有意义。当然,你可以提出自己的列排序准则,因为计算部分并不受列顺序的影响。
统计DataFrame摘要信息
在1.7节“调用Series方法”中,对单个列或Series数据使用了多种方法进行操作。其中许多是返回单个标量值的聚合(aggregation)或归约(reduce)方法。在使用DataFrame调用这些相同的方法时,它们会立即对每一列执行操作,并归约DataFrame中每一列的结果。它们将返回一个Series,在索引中包含列名称,并汇总每一列作为值。
在本秘笈中,我们将对movie数据集探索各种最常见的DataFrame属性和方法。
实战操作
(1)读取movie数据集,检查其基本描述性属性,如.shape、.size和.ndim,另外还可以运行len函数。
>>> movies = pd.read_csv("data/movie.csv")
>>> movies.shape
(4916, 28)
>>> movies.size
137648
>>> movies.ndim
>>> len(movies)
4916
(2).count方法可以显示每一列的非缺失值数。这是一种聚合方法,因为.count方法可以将单个列汇总为一个值。其输出是一个以原始列名作为索引的Series。
>>> movies.count()
color 4897
director_name 4814
num_critic_for_reviews 4867
duration 4901
director_facebook_likes 4814
title_year 4810
actor_2_facebook_likes 4903
imdb_score 4916
aspect_ratio 4590
movie_facebook_likes 4916
Length: 28, dtype: int64
(3)计算摘要统计信息的其他方法还包括.min(最小值)、.max(最大值)、.mean(平均值)、.median(中值)和.std(标准差),它们将返回一个Series,其中包含列名称(作为索引),并使用聚合结果作为值。
>>> movies.min()
num_critic_for_reviews 1.00
duration 7.00
director_facebook_likes 0.00
actor_3_facebook_likes 0.00
actor_1_facebook_likes 0.00
title_year 1916.00
actor_2_facebook_likes 0.00
imdb_score 1.60
aspect_ratio 1.18
movie_facebook_likes 0.00
Length: 16, dtype: float64
(4).describe方法非常强大,可以立即计算所有描述性统计数据和四分位数。最终结果是一个以描述性统计信息名称作为索引的DataFrame。笔者喜欢使用.T转置结果,因为这样做通常可以在屏幕上显示更多信息。
>>> movies.describe().T
count mean ... 75% max
num_criti... 4867.0 137.988905 ... 191.00 813.0
duration 4901.0 107.090798 ... 118.00 511.0
director_... 4814.0 691.014541 ... 189.75 23000.0
actor_3_f... 4893.0 631.276313 ... 633.00 23000.0
actor_1_f... 4909.0 6494.488491 ... 11000.00 640000.0
... ... ... ... ... ...
title_year 4810.0 2002.447609 ... 2011.00 2016.0
actor_2_f... 4903.0 1621.923516 ... 912.00 137000.0
imdb_score 4916.0 6.437429 ... 7.20 9.5
aspect_ratio 4590.0 2.222349 ... 2.35 16.0
movie_fac... 4916.0 7348.294142 ... 2000.00 349000.0
(5)可以使用percentiles参数在.describe方法中指定精确的分位数。
>>> movies.describe(percentiles=[0.01, 0.3, 0.99]).T
count mean ... 99% max
num_criti... 4867.0 137.988905 ... 546.68 813.0
duration 4901.0 107.090798 ... 189.00 511.0
director_... 4814.0 691.014541 ... 16000.00 23000.0
actor_3_f... 4893.0 631.276313 ... 11000.00 23000.0
actor_1_f... 4909.0 6494.488491 ... 44920.00 640000.0
... ... ... ... ... ...
title_year 4810.0 2002.447609 ... 2016.00 2016.0
actor_2_f... 4903.0 1621.923516 ... 17000.00 137000.0
imdb_score 4916.0 6.437429 ... 8.50 9.5
aspect_ratio 4590.0 2.222349 ... 4.00 16.0
movie_fac... 4916.0 7348.294142 ... 93850.00 349000.0
原理解释
步骤(1)提供了有关数据集大小的基本信息。其中:.shape属性可以返回包含行和列数的元组;.size属性返回DataFrame中元素的总数,这其实就是行和列数的乘积;.ndim属性返回维数,对于所有DataFrame,维数均为2。
将DataFrame传递给内置len函数时,该函数将返回行数。步骤(2)和步骤(3)中的方法可以将每一列汇总为一个数字。现在,每个列名都是Series中的索引标签,其聚合结果为相应的值。
通过仔细观察可注意到,步骤(3)的输出缺少步骤(2)的所有对象列,这是因为此方法默认情况下忽略字符串列。
可以看到,虽然数字列中包含缺失值,但是.describe方法也返回了结果。这是因为,默认情况下,Pandas遇到数值列中的缺失值时会跳过。通过将skipna参数设置为False,可以更改此行为。在将skipna参数改为False之后,只要存在一个缺失值,就会导致Pandas为所有这些聚合方法返回NaN。
.describe方法可以显示数字列的摘要统计信息。通过将0~1的数字列表传递给percentiles参数,可以扩展其摘要以包括更多分位数。有关.describe方法的更多信息,请参见4.2节“开发数据分析例程”。
扩展知识
要查看.skipna参数如何影响结果,我们可以将其值设置为False,然后重新运行步 骤(3)。在这种情况下,只有不包含缺失值的数字列才会返回计算的结果。
>>> movies.min(skipna=False)
num_critic_for_reviews NaN
duration NaN
director_facebook_likes NaN
actor_3_facebook_likes NaN
actor_1_facebook_likes NaN
title_year NaN
actor_2_facebook_likes NaN
imdb_score 1.6
aspect_ratio NaN
movie_facebook_likes 0.0
Length: 16, dtype: float64
推荐书单
《Pandas1.x实例精解》
本书详细阐述了与Pandas相关的基本解决方案,主要包括Pandas基础,DataFrame基本操作,创建和保留DataFrame,开始数据分析,探索性数据分析,选择数据子集,过滤行,对齐索引,分组以进行聚合、过滤和转换,将数据重组为规整形式,组合Pandas对象,时间序列分析,使用Matplotlib、Pandas和Seaborn进行可视化,调试和测试等内容。此外,本书还提供了相应的示例、代码,以帮助读者进一步理解相关方案的实现过程。本书适合作为高等院校计算机及相关专业的教材和教学参考书,也可作为相关开发人员的自学用书和参考手册。
精彩回顾
利用Pandas操作DataFrame的列与行
《Pandas1.x实例精解》新书抢先看!
想用Python赚钱?——安排!
pandas分组排序时候,组内的数据如何排序,以及排序的标号如何显示(连续,跳跃等)
常用语法:
df.groupby(['company'])['salary'].rank(ascending=0, method='dense')
ascending = 0 :降序;ascending = 1 :升序;
method的数值比较多,下面分开讲讲。
数据集:
1、method = "dense"
2、method = 'first'
3、method = 'min'
4、method = 'max'
上一节链接: 喜滋滋乐悠悠:Pandas—分组排序—groupby-rank
点个赞,再走。
1.groupby 分组
我们经常需要将数据根据某个字段划分为不同的组(group)进行分析,然后对组里的数据进行特定的操作。
groupby的过程就是将原有的DataFrame按字段,划分为若干个分组后的子DataFrame。在groupby之后的一系列操作(如agg、apply等),均是基于子DataFrame的操作。
1.1数组构造
# 数据构造
df = pd.DataFrame({"城市":["Russian","China","America","Brazil","China","Japan","America"],
"航班":[1170, 960, 980, 800, math.nan, 300, 3244],
"人口":[1, 13, math.nan, 2, 14, 3, 5]})
1.2分组
# 对‘城市’列进行数据分组
group = df.groupby("城市")
list(group)
从上图中可看出一共有5个子分组。
注:使用groupby后可以在子dataframe上应用 count,mean,unique等统计方法
1.3分组后统计
# 对‘城市’列进行数据分组后进行‘航班’列的数量统计
df.groupby("城市").航班.count()
2.rank 分组排名
对分完组的数据,如果还要做排名(非排序)操作,可以用到rank函数。
rank方法中可以通过method参数指定不同的排名方法,下面的示例中将详细说明。
1.1数据构造
# 数据构造