Pandas简介
在数据分析工作中,Pandas 的使用频率是很高的,一方面是因为 Pandas 提供的基础数据结构 DataFrame 与 json 的契合度很高,转换起来就很方便。另一方面,如果我们日常的数据清理工作不是很复杂的话,你通常用几句 Pandas 代码就可以对数据进行规整。Pandas 可以说是基NumPy 构建的含有更高级数据结构和分析能力的工具包。
数据结构:Series 和 DataFrame
Series 和 DataFrame 这两个核心数据结构,他们分别代表着一维的序 列和二维的表结构。基于这两种数据结构,Pandas 可以对数据进行导入、清洗、处理、统计和输出。
Series 是个定长的字典序列。说是定长是因为在存储的时候,相当于两个 ndarray,这也是和字典结构最大的不同。因为在字典的结构里,元素的个数是不固定的。
Series有两个基本属性:index 和 values。在 Series 结构中,index 默认是 0,1,2,……递增的整数序列,当然我们也可以自己来指定索引,比如 index=[‘a’, ‘b’, ‘c’, ‘d’]。
DataFrame 类型数据结构类似数据库表。它包括了行索引和列索引,我们可以将 DataFrame 看成是由相同索引的 Series 组成的字典类型。
Pandas常用统计函数
实际应用示例一
import pandas as pd from pandas import Series, DataFrame x1 = Series([1,2,3,4]) x2 = Series(data=[1,2,3,4], index=['a', 'b', 'c', 'd']) print (x1) print (x2) # 这个例子中,x1 中的 index 采用的是默认值,x2 中 index 进行了指定。我们也可以采用 # 字典的方式来创建 Series,比如 d = {'a':1, 'b':2, 'c':3, 'd':4} x3 = Series(d) print (x3) data = {'Chinese': [66, 95, 93, 90,80],'English': [65, 85, 92, 88, 90],'Math': [30, 98,96,77,90]} df1= DataFrame(data) df2 = DataFrame(data, index=['ZhangFei', 'GuanYu', 'ZhaoYun', 'HuangZhong', 'DianWei']) print (df1) print (df2) #Pandas 允许直接从 xlsx,csv 等文件中导入数据,也可以输出到 xlsx, csv 等文件,非常方便。 # score = DataFrame(pd.read_excel('data.xlsx')) # score.to_excel('data1.xlsx') # print (score) #更改数据格式 #df2['Chinese'].astype('str') # df2['Chinese'].astype(np.int64) # 有时候我们先把格式转成了 str 类型,是为了方便对数据进行操作,这时想要删除数据间的 # 空格,我们就可以使用 strip 函数: # 删除左右两边空格 df2['Chinese']=df2['Chinese'].astype('str').map(str.strip) # 删除左边空格 df2['Chinese']=df2['Chinese'].astype('str').map(str.lstrip) # 删除右边空格 df2['Chinese']=df2['Chinese'].astype('str').map(str.rstrip) # 全部大写 df2.columns = df2.columns.str.upper() # 全部小写 df2.columns = df2.columns.str.lower() # 首字母大写 df2.columns = df2.columns.str.title() #把"张飞"这行删掉。 df2 = df2.drop(index=['ZhangFei']) #把"语文"这列删掉 # df2 = df2.drop(columns=['Chinese']) # 如果你想对 DataFrame 中的 columns 进行重命名,可以直接使用 # rename(columns=new_names, inplace=True) 函数,比如我把列名 Chinese 改成 # YuWen,English 改成 YingYu。 df2.rename(columns={'Chinese': 'YuWen', 'English': 'Yingyu'}, inplace = True) # 去除重复行 df2 = df2.drop_duplicates() #如果我们想看下哪个地方存在空值 NaN,可以针对数据表 df 进行 df2.isnull() #如果我想知道哪列存在空值,可以使用 df3=df2.isnull().any() print(df3) df2['YuWen'] = df2['YuWen'].apply(str.upper) def double_df(x): return 2*x df2['YuWen'] = df2['YuWen'].apply(double_df) # 我们也可以定义更复杂的函数,比如对于 DataFrame,我们新增两列,其中’new1’列 # 是“语文”和“英语”成绩之和的 m 倍,'new2’列是“语文”和“英语”成绩之和的 n # 倍,我们可以这样写: def plus(df,n,m): df['new1'] = (df['Math']+df['Yingyu']) * m df['new2'] = (df['Math']+df['Yingyu']) * n return df df2 = df2.apply(plus,axis=1,args=(2,3,)) print(df2) # 其中 axis=1 代表按照列为轴进行操作,axis=0 代表按照行为轴进行操作,args 是传递的 # 两个参数,即 n=2, m=3,在 plus 函数中使用到了 n 和 m,从而生成新的 df。 # describe() 函数,统计函数千千万,describe() 函数最简便。它是个统计大 # 礼包,可以快速让我们对数据有个全面的了解。下面我直接使用 df1.descirbe() df1 = DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)}) print (df1.describe()) df1 = DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)}) df2 = DataFrame({'name':['ZhangFei', 'GuanYu', 'A', 'B', 'C'], 'data2':range(5)}) #基于 name 这列进行连接。 df3 = pd.merge(df1, df2, on='name') # inner 内链接是 merge 合并的默认情况,inner 内连接其实也就是键的交集,在这里 df1, # df2 相同的键是 name,所以是基于 name 字段做的连接: df3 = pd.merge(df1, df2, how='inner') df3 = pd.merge(df1, df2, how='left') df3 = pd.merge(df1, df2, how='right') df3 = pd.merge(df1, df2, how='outer') # Pandas 的 DataFrame 数据类型可以让我们像处理数据表一样进行操作,比如数据表的增 # 删改查,都可以用 Pandas 工具来完成。不过也会有很多人记不住这些 Pandas 的命令, # 相比之下还是用 SQL 语句更熟练,用 SQL 对数据表进行操作是最方便的,它的语句描述形 # 式更接近我们的自然语言。 # 事实上,在 Python 里可以直接使用 SQL 语句来操作 Pandas。 from pandasql import sqldf, load_meat, load_births df1 = DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)}) pysqldf = lambda sql: sqldf(sql, globals()) sql = "select * from df1 where name ='ZhangFei'" print (pysqldf(sql))
实际应用示例二
import boto3 import pandas as pd client = boto3.client( "s3", endpoint_url="https://xxx", aws_access_key_id="aws_access_key_id", aws_secret_access_key="aws_secret_access_key", ) def get_part_from_path(path): table = path.split("/")[2] return table def get_endswith(path): ends = path[-1] return ends def stat_aws(bucket, prefix): marker = "" data = [] while True: res = client.list_objects( Bucket=bucket, Prefix=prefix, Marker=marker, ) marker = res.get("NextMarker") # Key,LastModified,ETag,Size,StorageClass,Owner data += res.get("Contents", []) if marker is None: break df = pd.DataFrame(data) return df bucket_prefix = { 'bucket_name': [''hive/ao_dodo/'], } if __name__ == '__main__': pd.set_option('display.unicode.ambiguous_as_wide', True) #处理数据的列标题与数据无法对齐的情况 pd.set_option('display.unicode.east_asian_width', True) #无法对齐主要是因为列标题是中文 pd.set_option('display.max_columns', None) #显示所有列 #pd.set_option('display.max_rows', None) #显示所有行 pd.set_option('display.width', 300) #数据显示总宽度 for bucket in bucket_prefix: for prefix in bucket_prefix[bucket]: df = stat_aws(bucket, prefix) print(df) # inplace=False(默认)表示原数组不变,对数据进行修改之后结果给新的数组。 # inplace=True表示直接在原数组上对数据进行修改。 # 删掉key列中所有以'/'结尾的行 df.drop(df.index[(df['Key'].apply(get_endswith) == '/')], inplace=True) print(df) df["cnt"] = 1 df["table_name"] = df["Key"].apply(get_part_from_path) print(df) #df.reset_index() # 会将原来的索引index作为新的一列 df_res = df.groupby("table_name")["Size","cnt"].sum().reset_index() print(df_res) df_res = df.groupby('table_name').agg( {'Size': ['sum'], 'cnt': ['sum'], 'LastModified': ['max']}).reset_index() print(df_res) df_res['bucket'] = bucket df_res['prefix'] = prefix df_res["size_gb"] = df_res["Size"] / 1024 ** 3 df_res["all_size_prefix_gb"] = df_res["size_gb"].sum() df_res.columns = pd.Series( ['table_name', 'Size', 'cnt', 'LastModified', 'bucket', 'prefix', 'size_gb', 'all_size_prefix_gb']) print(df_res) df_res.drop(index=[0], inplace=True) print(df_res) break print('cosSize')
print(df)
print(df_res)
拓展阅读
Python pandas数据分析中常用方法_青盏的博客-CSDN博客