分享

一万字的Pandas常用知识点介绍加案例

 NeighborMrSun 2023-02-13 发布于湖南

回复 红包 可以领程序员专属红包封面

Pandas简介

Pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);
用于数据挖掘和数据分析,同时也提供数据清洗功能。

1. Series

它是一种类似于一维数组的对象,是由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。
仅由一组数据也可产生简单的Series对象

1.1. 使用list构建Series

默认index是数字

import pandas as pd
import numpy as np
 
# 自定义打印的函数,方便后面调试
def _print(s: str, *args, pad=20):
    print('\n', s.center(pad, '-'))
    for i in args:
        print(i)
 
infoLi = ['jack'18'180CM']
serLi = pd.Series(data=infoLi)
_print('list构建Series', serLi)
serLi = pd.Series(data=infoLi, index=list('abc'))
_print('list构建Series,并指定index', serLi)

图片

1.2. 使用字典构建Series

index为字典的key

infoDic = {'name''jack''age'18'height''180CM'}
serDic = pd.Series(data=infoDic)
_print('字典构建Series', serDic)

1.3. Series转换为list

infoLi = serLi.tolist()
_print('Series转换为list', infoLi)

1.4. Series转换为dict

infoDic = serDic.to_dict()
_print('Series转换为dict', infoDic)

1.5. Series转换为DataFram

df = pd.DataFrame(data=serDic)
_print('Series转换为DataFram', df)
df = pd.DataFrame(data=serDic, columns=['信息'])
_print('Series转换为DataFram,并指定列名', df, pad=30)

1.6. 修改Series的数据类型

s = pd.Series(data=['001''002'], index=list('ab'))
_print('构建Series', s)
1.6.1. astype
sastype = s.astype(int)
_print('使用astype函数修改数据类型', sastype)
1.6.2. map

map函数可以将一个匿名函数作用于所有的数据上
相当于遍历了一遍Series,对每一个值执行了float()方法

smap = s.map(lambda x: float(x))
smap = s.map(float)
_print('使用map修改数据类型', smap)

1.7. 使用concat给Series添加新的元素

使用concat将一个Series追加原Series后面

sCon = pd.Series(data=['003''004'], index=['c''d'])
s = pd.concat([s, sCon])
_print('concat追加新元素', s)

> 指定axis=1,横向追加,两个Series横向追加会变成DataFrame
df = pd.concat([s, sCon], axis=1)
_print('concat追加新元素,并指定axis=1', df)

2. 构建DataFrame

DataFrame是Pandas中的一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。

2.1 字典转换为DataFram

2.1.1. 字典的value不是列表
> 如果字典的key不是列表,需要指定index,或者使用items()取出k,v
infoDic = {'name''jack''age'18'height''180CM'}
df = pd.DataFrame(data=infoDic, index=[0])
_print('指定index=[0]', df)
# 使用items()取出k,v
df = pd.DataFrame(data=list(infoDic.items()))
_print('使用items()取出k,v', df)

2.1.2. 字典的value是列表

infoDic = {'id': [12], 'name': ['jack''rose'], 'age': [1818], 'height': ['180CM''170CM']}

df = pd.DataFrame(data=infoDic)
_print('v是列表', df)

2.2. 使用列表创建DataFrame

columns也可以不指定

df = pd.DataFrame([[12], [1112]], columns=['c1''c2'], index=['i1''i2'])

_print('使用list创建DataFrame', df)

2.3. 使用numpy创建DataFrame

创建一个np.arange()可以创建一维ndarray,reshape是修改形状,这里修改成了3行4列的二维ndarray
同样,直接使用list创建也行

df = pd.DataFrame(np.arange(12).reshape(34))
_print('使用numpy创建DataFrame', df)

2.4 构建一个稍复杂DataFrame

index为100个日期,字段内容为正态分布和均匀分布随机数

date_range = pd.date_range(start='2022-01-01', periods=100)  # date_rage可以生成各种类型的日期
data = {
    'normal': np.random.normal(loc=0, scale=1, size=100),  # 正态分布
    'uniform': np.random.uniform(low=0, high=1, size=100)  # 均匀分布
}
df = pd.DataFrame(data=data, index=date_range)
_print('复杂DataFrame', df)

3. 查看DataFrame

df = pd.read_csv('./IMDB-Movie-Data.csv')
3.1. info

查看dataframe的描述信息

_print('info', df.info)
3.2. dtypes

查看数据类型

_print('dtypes:', df.dtypes)
df['Title'].astype('string')
3.3. tail

查看后面几行

_print('tail', df.tail(10))
3.4. head

查看数据前几行

_print('head', df.head(10))
3.5. 按列查看
3.5.1 取单列
_print('取单列', df['Rank'])
3.5.2. 取多列

注意是两个中括号

_print('取多列', df[['Rank''Title''Metascore']])
3.6. 按行查看

可以将列表的切片思想直接拿过来用

_print('按行取', df[0:2])
3.7. loc

可同时按照行和列进行取值

_print('loc', df.loc[0:2'Rank':'Metascore'])
3.8. iloc

可同时按照行和列进行取值,使用数字下标

_print('iloc', df.iloc[0:21:3])
3.9. 字符串操作

所有字符串操作均可以,这里只列举几个

_print('字符串操作', df['Title'].head())
_print('str.upper', df['Title'].str.upper())
_print('str.replace', df['Title'].str.replace(' ''/'))
_print('str.split', df['Title'].str.split(' '))
3.10. 布尔值过滤

如果多个条件,每个条件用()括起来,并且用& 或者用|

3.10.1. 取出Rank为偶数的行
print(df[(df['Rank'] % 2 == 0)])
3.10.2. 取出Rank小于10,并且Metascore大于70的行
print(df[(df['Rank'] < 10) & (df['Metascore'] > 70)])

4. 修改

4.1. 修改DataFrame的列
df = pd.DataFrame(data=[[12]])
df.columns = ['col1''col2']
_print('columns修改所有列名:', df)
df.rename(columns={'col1''c1'}, inplace=True)
_print('rename修改指定列名:', df)
4.2. 修改指定值
df.loc[0'c1'] = 11
_print('修改指定值:', df)

5. Null值处理

df = pd.DataFrame(data=np.full((34), np.nan), columns=list('abcd'), index=list('xyz'))
df.loc['x''a'], df.loc['y''a'], df.loc['x''b'] = 123
print(df)

5.1. 判断是否为NAN

_print('判断是否为NaN', df.isnull())
_print('判断是否为NaN', df.isna())
_print('判断是否不为NaN', df['a'].notnull())

5.2. fillna修改NaN的值

df_f_1 = df.fillna(0)
df_f_2 = df.fillna(method='ffill')
_print('原样:', df)
_print('使用前一个填充', df_f_2)
print('-----NaN填充为列平均值-----')
for i in df:
    if df[i].isna().any():
        df[i].fillna(value=df[i].mean(), inplace=True)
print(df)

6. 排序

df = pd.read_csv('./IMDB-Movie-Data.csv')

_print('df', df)

6.1. 按索引排序sort_index

ascending:指定排序方式,na_position:NaN值放在头还是尾

df.sort_index(inplace=True, ascending=False, na_position='first')
_print('sort_index', df)

6.2. 按值排序 sort_values

by:按照哪个字段排序

df.sort_values(by=['Revenue (Millions)''Metascore'], inplace=True, ascending=True, na_position='last')
_print('sort_values', df[['Revenue (Millions)''Metascore']].head(20))

7. 索引

7.1 设置DataFrame的索引列

_print('info:', df)
df.set_index(keys=['Rank''Title'], inplace=True)
_print('使用set_index修改索引列:', df)
7.2 重置DataFrame的索引列
df.reset_index(inplace=True)
_print('使用reset_index重置索引列:', df)

8. 表连接

left = pd.DataFrame(np.arange(6).reshape(32), columns=['a''b'], index=['i1''i2''i3'])
right = pd.DataFrame(np.arange(410).reshape(32), columns=['c''d'], index=['i1''i2''i23'])
_print('_left', left)
_print('right', right)
8.1. join

将n个datafram进行合并,和SQL的逻辑一模一样
注意:两个Dataframe的字段名不能相同

# inner 内连接,取行索引的交集,不匹配的不展示
inner = left.join(right, how='inner')
_print('inner', inner)
# outer 外连接,取行索引的并集,不匹配的显示NaN
outer = left.join(right, how='outer')
_print('outer', inner)
# left 左连接,使用左边df的行索引,左侧全展示,右侧不匹配的显示NaN
outer_l = left.join(right, how='left')
_print('outer_l', outer_l)
# right 右连接,使用右边df的行索引,右侧全展示,左侧不匹配的显示NaN
outer_r = left.join(right, how='right')
_print('outer_r', outer_r)
8.2. merge

left左表,right右表,left_on,right_on两个表的关联字段

merge = pd.merge(left=left, right=right, left_on='b', right_on='d', how='left')
_print('merge', merge)

9. 聚合

SQL的聚合函数都可以使用

df = pd.read_csv('./IMDB-Movie-Data.csv')
_print('df', df)
_print('sum', df.sum())
_print('mean', df.mean())
_print('count', df.count())
_print('min', df.min())
_print('max', df.max())
9.1. agg

一次性使用多个聚合函数

agg = df.agg(['mean''sum''max'])
_print('agg', agg)

9.2. agg不同字段不同函数

agg = df.agg({'Rank': ['sum''min'], 'Metascore': ['max''min']})
_print('agg不同字段不同函数', agg)

10. 窗口函数

10.1. rolling
df = pd.DataFrame(np.random.randint(110, size=32).reshape(84),
                  index=pd.date_range('12/1/2020', periods=8),
                  columns=['A''B''C''D'])
_print('开窗', df)

# 3个数求一次均值
df['A_rolling'] = df['A'].rolling(window=3).mean()
_print('rolling', df)

10.2. expanding

expanding 又叫扩展窗口函数,扩展是指由序列的第一个元素开始,逐个向后计算元素的聚合值

# 1个开始,每次都累加上之前的值
df['A_expanding'] = df['A'].expanding(min_periods=2).sum()
_print('expanding', df)
10.3. shift

移动函数,可以获得某列前后n行的值,可以计算同比环比

# 获得A列后面一个的值
df['A_shift+1'] = df['A'].shift(periods=1)
_print('shift', df)
# 获得A列前面一个的值
df['A_shift-1'] = df['A'].shift(periods=-1)
_print('shift', df)

11. 列转行

列转行就是把列名提到行里面去

df = pd.DataFrame([['张三'1020], ['李四'3040]], columns=['姓名''语文''数学'])
print(df)
11.1. stack

需要将不变的列设置为索引(原始字段为姓名,语文,数学,转换后为姓名,科目,成绩。姓名字段不变)

df_stack = df.set_index('姓名').stack()
_print('df_stack', df_stack)
df_stack = df_stack.reset_index()  # 重置索引
_print('df_stack重置索引', df_stack)
df_stack.columns = ['姓名''科目''成绩']
_print('df_stack,设置列名', df_stack)
11.2. melt

id_vars:列转行后,不变的那一列
value_vars:列转行后,需要变动的那些列的列名
var_name:列转为行后,value_vars所属的字段名 http://qn./202211181539833.png
value_name:列转为行后,新表的值那一列的列明

df_melt = df.melt(id_vars='姓名', value_vars=['语文''数学'], var_name='科目', value_name='成绩')
_print('df_melt', df_melt)

12. 行转列

行转列就是把行里的值提成列名

tmp = pd.DataFrame({'姓名': ['张三''李四''王五''张三''李四''王五''张三''李四''王五'],
                    '科目': ['英语''英语''英语''数学''数学''数学''语文''语文''语文'],
                    '分数': [906070809880859075]})

_print('行转列原始数据', tmp)

12.1. unstack

tmp2 = tmp.set_index(['姓名''科目'])['分数'].unstack().reset_index()
_print('行转列unstack', tmp2)
df = tmp2.rename_axis(columns=None)  # 消除科目两个字
_print('行转列unstack', df)

12.2. pivot

df = tmp.pivot(index='姓名', columns='科目', values='分数').reset_index().rename_axis(columns=None)
print(df)

13. 小案例

13.1. 新增一个字段,内容为所有父级ID,例:1.0->3.0->8

df = pd.DataFrame([(1'总裁室', np.NaN),
                   (2'研发部'1),
                   (3'市场部'1),
                   (4'后端'2),
                   (5'前端'2),
                   (6'大数据'2),
                   (7'数仓开发'6),
                   (8'数据分析'6)
                   ],
                  columns=['ID''PRODUCTNAME''PARENTID'])
print('*' * 100)


def get_order(argid, df):
    # 通过ID获取PARENTID
    pid = df.loc[df['ID'] == argid, 'PARENTID']
    # print(type(pid), pid) # Series类型
    pid = pid.values[0]  # 获取PARENTID的具体值
    if pd.isna(pid):
        return str(argid)
    else:
        return get_order(pid, df) + '->' + str(argid)


for i in df.values:
    df.loc[df['ID'] == i[0], ['ORDERID']] = get_order(i[0], df)
print(df)

13.2 计算以下列表中的字母出现次数

data = [{'word': ['a''q''a']}, {'word': ['qwe''qwe''a''asd']}, {'word': ['sd']}]

lst = []
for dic in data:
    lst.extend(dic['word'])
res = pd.Series(lst)  # Dataframe也行
res = res.value_counts().to_dict()
print(res)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约