|
思考:
对于一组电影数据,如果我们希望统计电影分类(genre)的情况,应该如何处理数据?
思路:重新构造一个全为0的数组,列名为分类,如果某一条数据中分类出现过,就让0变为1
import pandas as pd import numpy as np from matplotlib import pyplot as plt file_path = 'filepath' df = pd.read_csv(file_path) print(df.head(1)) print(df['Genre']) # 统计分类的列表 temp_list = df['Genre'].str.split(',').tolist() #[[],[],[]] genre_list = list(set(i for i in temp_list for i in j)) #去重 #构造全为0的数组,columns是每个分类 zeros_df = pd.DataFrame(np.zeros((df.shape[0],len(genre_list))),column = genre_list) print(zeros_df) #给每个电影出现分类的位置赋值1 for i in range(df.shape[0]): # zeros_df.loc[0,['sci-fi','musical']]=1,相当于取一行多列 zeros_df.loc[i,temp_list[i]]=1 #给出现分类的地方设为1 print(zeros_df.head(3)) # 统计每个分类电影的数量和 genre_count = zeros_df.sum(axis=0) print(genre_count) #排序 genre_count = genre_count.sort_values() _x = genre_count.index _y = genre_count.values #画图(条形图) plt.figure(figsize=(20,8),dpi=80) plt.bar(range(len(_x)),_y) plt.xticks(range(len(_x)),_x) plt.show()
一、数据合并之join
join:默认情况下他是把行索引相同的数据合并到一起
import pandas as pd import numpy as np df1 = pd.DataFrame(np.ones((2,4)),index=['A','B'],columns=list('abcd')) print(df1) df2 = pd.DataFrame(np.zeros((3,3)),index=list('ABC'),columns=list('xyz')) print(df2) print(df1.join(df2))
二、数据合并之merge
merge:按照指定的列把数据按照一定的方式合并到一起
df1 = pd.DataFrame(np.ones((2,4)),index=['A','B'],columns=list('abcd')) print(df1) df2 = pd.DataFrame(np.zeros((3,3)),index=list('ABC'),columns=list('xyz')) print(df2) df3 = pd.DataFrame(np.zeros((3,3)),columns=list('fax')) print(df1.merge(df3,on='a')) ''' Empty DataFrame Columns: [a, b, c, d, f, x] Index: [] ''' df3.loc[1,'a'] = 1 print(df3) print(df1.merge(df3,on='a'))
默认的合并方式inner,交集
merge outer,并集,NaN补全
merge left,左边为准,NaN补全
merge right,右边为准,NaN补全
df1 = pd.DataFrame(np.ones((2,4)),index=['A','B'],columns=list('abcd')) df3 = pd.DataFrame(np.arange(9).reshape((3,3)),columns=list('fax')) print(df1) print(df3) print(df1.merge(df3,on='a')) df1.loc['A','a'] = 100 print(df1) print(df1.merge(df3,on='a')) print(df1.merge(df3,on='a',how='inner')) # 内连接,取交集 print(df1.merge(df3,on='a',how='outer')) #外连接,取并集
三、数据的分组聚合功能
思考:现在我们有一组关于全球星巴克店铺的统计数据,如果我想知道美国星巴克数量和中国的哪个多,或者我想知道中国每个省份星巴克的数量情况,那么应该怎么办?
传统思路:遍历一遍,每次加1?
在pandas中类似的分组操作我们有很简单的方式完成:df.groupby(by='columns_name')
那么问题来了,调用group方法后,返回的是什么内容?答:返回一个DataFrameGroupBy对象,可以遍历,调用聚合方法
import pandas as pd import numpy as np file_path = 'filepath' df = pd.read_csv(file_path) print(df.head(1)) print(df.info()) grouped = df.groupby(by='Country') print(grouped) #返回一个DataFrameGroupBy对象,可以进行遍历,调用聚合方法 可以进行遍历, for i,j in grouped: print(i) print('-' * 10) print(j,type(j)) print('*'*10) == df[df['Country']='US']
调用聚合方法
print(grouped.count()) #统计每组数据的个数 country_count = grouped['Brand'].count() #统计具体哪组数据的个数 print(country_count['US']) #统计美国星巴克数量 print(country_count['CN'])
统计每个省份的店铺数量
#统计中国每个省份的店铺数量
# china_data = df[df['Country'] == 'CN']
# grouped = china_data.groupby(by = 'State/Province').count()['Brand']
# print(grouped)
grouped = df.groupby(by='columns_name')
grouped是一个DataFrameGroupBy对象,是可迭代的,grouped中的每一个元素是一个元组,元组里面是索引(分组的值),分组之后的DataFrame
那么回到之前的问题:
要统计美国和中国的星巴克数量,我们应该怎么做?
分组之后的每个DataFrame的长度?
长度是一个思路,但是我们有更多的方法(聚合方法)来解决这个问题
要统计美国和中国的星巴克数量,我们应该怎么做?
DataFrameGroupby对象有很多经过优化的方法
函数名 | 说明 |
count | 分组中非NA值的数量 |
sum | 非NA值的和 |
mean | 非NA值得平均值 |
median | 非NA值的算数中位数 |
std、var | 无偏(分组为n-1)标准差和方差 |
min、max | 非NA值的最小值和最大值 |
如果我们需要对国家和省份进行分组统计,应该怎么操作呢?
grouped = df.groupby(by=[df['Country'],df['State/Province']])
很多时候,我们只希望对获取分组之后的某一部分数据,或者说我们只希望对某几列数据进行分组,这时候我们应该怎么办?
获取分组之后的某一部分数据:
df.groupby(by=['Country','State/Province'])['Country'].count() #若对df内的全部信息进行分组,不需要加df # 对某几列数据进行分组: df['Brand'].groupby(by=[df['Country'],df['State/Province']]).count()
观察结果,由于只选择了一列数据,所以结果是Series类型,如果我想返回DataFrame类型呢?
数据按照多个条件进行分组,返回Series类型的
df['Brand'].groupby(by = [df['Country'],df['State/Province']]).count()
df['Brand']返回结果为Series类型的一列数据,前面带有两个索引(两个分组条件),所以在进行分组时需要在某列前面加上df,df[columns],数据按照多个条件进行分组,返回DataFrame类型取列的时候,列表[]中嵌套[],即[[]]
grouped1 = df['Brand'].groupby(by = [df['Country'],df['State/Province']]).count() == grouped2 = df.groupby(by = [df['Country'],df['State/Province']])[['Brand']].count() == grouped3 = df.groupby(by = [df['Country'],df['State/Province']]).count()[['Brand']] #[['Brand']]的[]中又取[]表示取多列,DataFrame类型
以上两条命令结果一样,和之前的结果的区别在于当前返回的是一个DataFrame类型
那么问题来了:和之前一个分组条件相比,当前返回结果的前两列是什么?
索引和复合索引
简单的索引操作
获取index:df.index
指定index:df.index=['x','y']
重新设置index:df.reindex(list('abcdef'))
指定某一列作为index:df.set_index('Country').index.unique()
假设a为一个DataFrame,那么当a.set_index(['c','d'])即设置两个索引的时候是什么样子的结果呢?
a = pd.DataFrame({'a':range(7),'b':range(7,0,-1),'c':['one','one','one','two','two','two','two'],'d':list('hjklmno')}) print(a) ''' a b c d 0 0 7 one h 1 1 6 one j 2 2 5 one k 3 3 4 two l 4 4 3 two m 5 5 2 two n 6 6 1 two o '''
Series的复合索引取值,直接在括号中写索引就可以了
DataFrame需要用.loc取里面的列内容
df1 = pd.DataFrame(np.ones((2,4)),index=['A','B'],columns=list('abcd')) print(df1.index) #Index(['A', 'B'], dtype='object') df1.index=['a','b'] print(df1.index) #Index(['a', 'b'], dtype='object') print(df1.reindex(['a','f'])) ''' a b c d a 1.0 1.0 1.0 1.0 f NaN NaN NaN NaN ''' print(df1.set_index('a')) #将当前数据的某一列作为索引 ''' b c d a 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 ''' print(df1.set_index('a').index) #Float64Index([1.0, 1.0], dtype='float64', name='a') print(df1.set_index('a',drop=False)) #将a列作为索引,并且不删除a列 ''' a b c d a 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 ''' print(df1['d'].unique()) # [1.] print(df1['a'].unique()) #[1.] print(df1.set_index('b').index.unique()) #Float64Index([1.0], dtype='float64', name='b') print(df1) ''' a b c d a 1.0 1.0 1.0 1.0 b 1.0 1.0 1.0 1.0 ''' print(df1.set_index('a','b')) #单索引 ''' b c d a 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 ''' print(df1.set_index(['a','b'])) ''' c d a b 1.0 1.0 1.0 1.0 1.0 1.0 1.0 ''' print(df1.set_index(['a','b']).index) #复合索引 ''' MultiIndex([(1.0, 1.0), (1.0, 1.0)], names=['a', 'b']) '''
a = pd.DataFrame({'a':range(7),'b':range(7,0,-1),'c':['one','one','one','two','two','two','two'],'d':list('hjklmno')}) print(a) ''' a b c d 0 0 7 one h 1 1 6 one j 2 2 5 one k 3 3 4 two l 4 4 3 two m 5 5 2 two n 6 6 1 two o ''' b = a.set_index(['c','d']) print(b) ''' a b c d one h 0 7 j 1 6 k 2 5 two l 3 4 m 4 3 n 5 2 o 6 1 ''' print(type(b)) # <class 'pandas.core.frame.DataFrame'> # #想取['one']['j']的值时 print(b.loc['one'].loc['j']) ''' a 1 b 6 Name: j, dtype: int64 ''' print(b.swaplevel().loc['h']) #从内层取索引时 ''' a b c one 0 7 ''' c = b['a'] print(c) print(type(c)) print(c['one']) print(c['one']['j']) d = a.set_index(['d','c'])['a'] print(d) #此时想取'one'分组的信息不太容易,可以将双重索引的位置交换 print(d.index) #当我们想从内层索引取值时,就用swaplevel对双重索引的位置进行转换 print(d.swaplevel()) print(d.swaplevel()['one'])
复合索引时,当我们想从内层索引取值时,就用swaplevel对双重索引的位置进行转换
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-10-19 21:57
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社