学习笔记2 | 表格数据处理——Pandas

目录

2.1数据结构

2.1.1 Series

2.1.2 DataFrame

2.2 常规数据读写

2.3 数据索引

2.3.1 中括号

2.3.2 loc索引

2.3.3 iloc索引

2.3.4 布尔索引

2.4 数据清洗

2.4.1 缺失值剔除

2.4.2 缺失值补全

2.4.3 重复值处理

2.4.4 数据转换

2.5 时间数据处理

2.5.1 时间数据格式

2.5.2  时间戳

2.5.3 date_range 生成时间序列

2.5.4 时间周期

2.5.5 Period_range 时间序列

2.5.6 时间增量

2.6 数据的拼接与合并

2.6.1 concat方法

2.6.2 merge方法

2.6.3 join方法

2.7 数据的分组与聚合

2.7.1 分组 groupby()

2.7.2 聚合 agg()、transform()

2.8 数据重塑

2.8.1 轴向旋转 pivot()、pivot_table()

2.8.2 堆叠 stack()

2.9 图表数据可视化


2.1数据结构

2.1.1 Series

#创建方法
#1.用数组创建
data = np.array(['a', 'b', 'c', 'd', 'e'])
ds = pd.Series(data)
ds = pd.Series(data, index=np.arange(1,6))
#2.用字典创建
data = {
    'a': 1., 
    'b': 2., 
    'c': 3., 
    'd': 4.
}
ds = pd.Series(data)
ds = pd.Series(data, index=['d', 'c', 'b', 'a']) #不改变元素对应索引,但改变顺序
ds = pd.Series(data, index=['b', 'c', 'a', 'f']) #缺少元素用nan填充
#3.标量创建,必须提供index
ds = pd.Series(5, index=[0, 1, 2, 3])


#属性和常用方法
#1.用数组创建
data = np.array(['a', 'b', 'c', 'd', 'e'])
ds = pd.Series(data)
ds = pd.Series(data, index=np.arange(1,6))
#2.用字典创建
data = {
    'a': 1., 
    'b': 2., 
    'c': 3., 
    'd': 4.
}
ds = pd.Series(data)
ds = pd.Series(data, index=['d', 'c', 'b', 'a']) #不改变元素对应索引,但改变顺序
ds = pd.Series(data, index=['b', 'c', 'a', 'f']) #缺少元素用nan填充
#3.标量创建,必须提供index
ds = pd.Series(5, index=[0, 1, 2, 3])

2.1.2 DataFrame

#创建方法
#1.ndarray / 字典
data = {'one':[1,2,3,4],'two':[4,3,2,1]}
df = pd.DataFrame(data)
df = pd.DataFrame(data, columns=['two', 'one']) #指定列顺序

data = {'one':np.arange(1, 6, 1), 'two':np.arange(5, 0, -1)}
df = pd.DataFrame(data, columns=['two', 'one'], index=['a', 'b', 'c', 'd', 'e'])

#2.Series创建
data = {
    'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
    'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
}
df = pd.DataFrame(data) #缺的补nan


#属性与方法
#1.属性
df.index
df.columns
df.axes
df.values, type(df.values)
df.ndim
df.size
df.shape
#2.方法
df.head(3)
df.tail(3)
df.info() #返回dataframe信息
df.describe()

2.2 常规数据读写

#读取
df = pd.read_csv('filename')
df.info()
pd.read_csv('URL/filename')
#分隔符 sep
#\s表示空白字符,包括但不限于空格、回车、换行、Tab,可用\s+
df = pd.read_csv('filename', delim_whitespace=True) #True时不设置delimiter

#表头
df = pd.read_csv('filename', sep=',', header=None) 默认第一行是表头
df = pd.read_csv('filename', sep=',', header=1) #纵向从0开始

#列名
df = pd.read_csv('filename', sep=',', names=range(38)) #0-37,此时保留原来表头,设置新表头
df = pd.read_csv('filename', sep=',', names=range(38), header=0)#覆盖表头=重新设置表头

#索引(行)
df = pd.read_csv('filename', index_col='hour')
df = pd.read_csv('filename', index_col=['date', 'hour', 'type'])

#使用部分列
df = pd.read_csv('filename', usecols=[0, 1, 2, 3])
df = pd.read_csv('filename', usecols=['东四', '天坛', '官园'])

#跳过指定行
df = pd.read_csv('filename', skiprows=[1,2,3,4])
df = pd.read_csv('filename', skiprows=[0]) #第0行被删掉,第一行变表头,第二行变第0行
df = pd.read_csv('filename', skiprows=[0],header=None)
df = pd.read_csv('filename', skiprows=8) #跳过前8行
df = pd.read_csv('filename', skiprows=lambda x: x % 2 != 0) #隔行跳过
#skip_blank_lines为True时跳过空行

#读取指定行
df = pd.read_csv('filename', nrows=10) #读取前10行

#通用解析函数
#表头前缀
df = pd.read_csv('filename', prefix='region_', header=None, skiprows=[0])

#列数据处理
df = pd.read_csv('filename', converters={'date': lambda x: pd.to_datetime(x)})
#把20200101变为2020-01-01 类型datetime64
df['date']
df['date'].dt.year, df['date'].dt.month, df['date'].dt.day #获取年月日

#空值替换
df = pd.read_csv('filename', na_values=20200101) #把日期变成nan了

#时间解析
df = pd.read_csv(
    'filename', 
    parse_dates={'time': ['date', 'hour']}, 
    converters={'hour': lambda x: x.zfill(2)}
    )
df.head()

#txt文件读取
pd.read_table('filename.txt')
pd.read_csv('filename', sep='\t')

2.3 数据索引

2.3.1 中括号

#1.列索引
df['name1']
df[['name1',	'name2',	'name3']]

#2.行索引
df[0:1]
df[0::5] #0 ,5 ,10, ...

#4.联合索引
df[2::5][['name1',	'name2',	'name3']]

2.3.2 loc索引

#1.行索引
df.loc[0] #返回一列
df.loc[[0]] #返回一行
df.loc[[0, 5]]
df.loc[3::5]

#2.列索引
df.loc[:, 'name1']
df.loc[:, ['name1',	'name2',	'name3']]

#3.联合索引
df.loc[4::5, ['name1',	'name2',	'name3']]

2.3.3 iloc索引

#1.行索引
df.iloc[5]
df.iloc[[5]]
df.iloc[:5] #0-4

#2.列索引
df.iloc[:, 3]
df.iloc[:, 0:10:2]

#3.联合索引
df.iloc[::10, 1:20:3]

2.3.4 布尔索引

df[df['type']=='n']
df[(df['type']=='n') & (df['name1']<=50)]
df[(df['type']=='n') | (df['type']=='m')].head()
df.loc[df['type'].isin(['n', 'm'])].head()
df[~(df['type'].isin(['p', 'q']))]

2.4 数据清洗

None表示空值,类型是NoneType,不支持任何运算

Nan(Not a number)类型是float

要先把None变成Nan

2.4.1 缺失值剔除

df.isnull()
df.isnull().sum() #计算每列的缺失个数
df.isnull().sum(axis='columns') #计算每行的缺失个数
df.isnull().all() #每列是否全部缺失,返回列个布尔
#DataFrame.drop(index= ,columns= ,inplace=False)
df1 = df.drop(columns='name1')
df1 = df.drop('name1', axis=1) #axis=1和column意思一样

df1 = df.loc[:, ~(df.isnull().all())] #剩下的列没有全缺测的
df1[~(df1.isnull().any('columns'))] #剩下的每行一个缺测的都没有
df.dropna(axis='columns', how='all', inplace=True) #inplace是替换当前df
df.dropna(axis='index', how='any')

2.4.2 缺失值补全

df.fillna(method='ffill')
df.fillna(method='bfill')
df.drop(columns='type').fillna(0)
df.interpolate()

2.4.3 重复值处理

df2 = df.append(df.iloc[-2:])
df2.duplicated() #返回布尔,某行是否是重复的
df2.drop_duplicates() #返回删除结果

#某列重复剔除
df2.duplicated(subset=['name1'], keep=False) #true是有重复
df[df['name1'] == 41]

2.4.4 数据转换

#1.replace
df.replace(np.nan, -9999)
df.replace([np.nan, 0], -9999)

#2.apply()某行,n列;applymap()
k = df[df['type']=='k']
def k_level(k):
    if k>0 and k<=50:
        level = '优'
    elif k>50 and k<=100:
        level = '良'
    elif k>100 and k<=150:
        level = '轻度污染'
    elif k>150 and k<=200:
        level = '中度污染'
    elif k>200 and k<=300:
        level = '重度污染'
    else:
        level = '严重污染'
    return level
k['name1'].apply(k_level)
k.loc[:, ~k.columns.isin(['date', 'hour', 'type'])].apply(np.mean, axis=0)
k.loc[:, ~k.columns.isin(['date', 'hour', 'type'])]
k.loc[:, ~k.columns.isin(['date', 'hour', 'type'])].applymap(k_level)

2.5 时间数据处理

2.5.1 时间数据格式

  1. 时间戳(timestamp)(datetimeindex):datetimes,to_datetime or date_range
  2. 时间周期(period)(periodindex):timespans, period or period_range
  3. 时间增量(timedelta)(timedeltaindex):timedeltas, to_timedelta or timedelta_range

2.5.2  时间戳

format 格式: datetime — Basic date and time types — Python 3.11.1 documentation

pd.Timestamp("2020/12/06") #Timestamp('2020-12-06 00:00:00')
pd.Timestamp(year=2020,month=12,day=6,hour=14,minute=19,second=52) #Timestamp('2020-12-06 14:19:52')

pd.Timestamp(df['date'][0]) #df['date'][0]是20200101,得到Timestamp('1970-01-01 00:00:00.020200101')
date = pd.to_datetime(df['date'][0]) #Timestamp('1970-01-01 00:00:00.020200101')
date = pd.to_datetime(df['date'][0], format='%Y%m%d') #Timestamp('2020-01-01 00:00:00')

#timestamp的属性
date.year
date.month
date.day
date.hour
date.minute
date.second
date.week
date.weekofyear

2.5.3 date_range 生成时间序列

pd.date_range('2020-01-01', '2020-02-08') #得到频率是每天
pd.date_range('2020-01-01', '2020-01-02', freq='H')
pd.date_range('2020-01-01', '2020-01-02', periods=24)
df.index = pd.date_range('2020-01-10', freq='D', periods=len(df.index))

#时间的索引
df = pd.read_csv(
    'filename.csv', 
    parse_dates={'time': ['date', 'hour']}, 
    converters={'hour': lambda x: x.zfill(2)}
    )
df.index = df.time
df.drop(columns='time')
df['2020-01-01 20:00': '2020-01-01 22:00']

2.5.4 时间周期

#1.生成时间周期
pd.Period("2020/12/06")
time -3 #3天
pd.Period("2020/12/06", 'H')
time -3 #3小时
time = pd.Period(freq='S',year=2015, month=3,day=19, minute=43)

#2.period属性
time.freqstr
time.day
time.month
time.year

2.5.5 Period_range 时间序列

pd.period_range('2008/8/1', '2010/1/1', freq='M')
dates = pd.period_range(start='2010-01', freq='3M', periods=8)
dates + 1 #1是3个月

2.5.6 时间增量

pd.Timedelta(1, unit='D')
pd.Period("2020/12/06") + pd.Timedelta(1, unit='D') #加一天
pd.Period("2020/12/06") + pd.Timedelta(days=2) #加两天
pd.Timestamp("2020/12/06") + pd.Timedelta(hours=2) #加2小时
pd.DateOffset(year=2)
pd.Timestamp("2020/8/06") + pd.DateOffset(years=2, months=1, days=1)

2.6 数据的拼接与合并

  1. concat对series或dataframe进行行或列拼接
  2. merge将不同行连接起来
  3. join主要基于多个dataframe的索引进行合并

2.6.1 concat方法

默认行拼接,取并集

import pandas as pd
import glob
files = list(glob.glob('./地址/*'))
dfl = []
for f in files:
    df = pd.read_csv(f)
    dfl.append(df)
dfl[2]
pd.concat(dfl)
pd.concat(dfl, ignore_index=True)
pd.concat(dfl, keys=['1日', '2日', '3日'])

#行拼接
dfl = []
for f in files:
    df = pd.read_csv(f)
    dfl.append(df.T)
pd.concat(dfl, axis='columns')

#取交集
df1 = pd.read_csv(files[0])
df2 = pd.read_csv(files[1], usecols=[3,4,5,6])
pd.concat([df1, df2]), join='inner')

2.6.2 merge方法

df_left = pd.read_csv(files[0], usecols=range(8))
df_right=pd.read_csv(files[0],nrows=10,usecols=[0,1,2]+list(range(10,15))).append({'date':'8888'},ignore_index=True)
pd.merge(df_left,df_right) #默认取了交集
pd.merge(df_left,df_right,how='left') #left以左边的列为参考,右边没有的补nan
pd.merge(df_left, df_right, how='outer') #outer取并集
pd.merge(df_left,df_right,on=['hour','type','date'])#on是相同列合并

2.6.3 join方法

基于行索引上的合并

dataframe.join(other,on=None,how='',lsuffix='',rsuffix='',sort=False)
df=pd.read_csv(files[0],usecols=range(3,6),nrows=15)
others = pd.read_csv(files[0],usecols=range(10,13),nrows=8)
df.join(others)
others.join(df)
df.join(others,how='inner')

#若两个表格有重复列
df=pd.read_csv(files[0],usecols=range(6),nrows=15)
others = pd.read_csv(files[0],usecols=range[0,1,2]+list(range(10,15)),nrows=8)
df.join(others,lsuffix='_df',rsuffix='_others'

2.7 数据的分组与聚合

2.7.1 分组 groupby()

import pandas as pd
import glob
files=glob.glob('../data/C3.7/*')
df=pd.concat([pd.read_csv(f) for f in files])
df.dropna(axis='columns',how='all').dropna(axis='index',how='any')

df['date']=df.apply({'date':lambda x:pd.to_datetime(x,format='%Y%m%d')})
df['month']=df['date'].dt.month

#datafram.groupby(by= ,axis=0,level= ,
group = df.groupby('type') #简单分组
for i in group:
   print(i)
df[df['type']=='AQI']

#2.多重分组
group = df.groupby(['type','month'])
for i in group:
    print(i)
df[df['type']=='AQI' & df['month']==1]

2.7.2 聚合 agg()、transform()

#1.内置统计方法 2.agg 3.transform
#1. count,head,max,mean,median,cumcount,size,min,std,sum

aqi = df[df['type']=='AQI']
aqi.groupby('hour').max()
aqi.groupby(['hour','month']).mean()

#2.dataframe.agg(func,axis=0)
#对每列应用相同的函数
aqi.groupby(['month','hour']).agg([np.mean,np.std])
#对每列应用不同的函数
aqi.groupby(['month','hour']).agg({'东四':[np.mean,np.std],'天坛':[np.max,np.min]})

#3.transform
aqi.groupby('month').agg(np.mean)
aqi.groupby('month').tramsform(np.mean)
aqi.groupby('month').tramsform(lambda x:x-x.mean())#距平

2.8 数据重塑

2.8.1 轴向旋转 pivot()、pivot_table()

import pandas as pd
import glob

files = list(glob.glob('../../*'))
df = pd.concat([pd.read_csv(f) for f in files],ignore_index=True)
df.dropna(axis='columns',how='all').dropna(axis='index',how='any')

df.pivot(index=['date','hour'],columns='type',values='东四') #透视表
df.pivot(index=['date','hour'],columns='type')

df.pivot_table(index=['date','hour'],columns='type',values='东四',aggfunc=np.mean))

2.8.2 堆叠 stack()

#1.stack() 2.unstack()
data = df.pivot_table(index=['date','hour'],columns='type')
data.stack() #变窄变长
data.unstack() #变宽变短

2.9 图表数据可视化

import pandas as pd
import glob
files = list(glob.glob('./地址/*.csv'))
df = pd.concat([pd.read_csv(f) for f in files], ignore_index=True)
df = df.dropna(axis='columns', how='all').dropna(axis='index', how='any')
df['time'] = df['date'].astype('str') + df['hour'].astype('str').apply(lambda x: x.zfill(2))
df['time'] = df['time'].apply(lambda x: pd.to_datetime(x, format='%Y%m%d%H'))
data = df.drop(columns=['date', 'hour']).pivot_table(index='time',  columns='type', values='东四')
aqi = data['AQI']
aqi.plot(backend='plotly')

data = df.drop(columns=['date', 'hour']).pivot_table(index='time',  columns='type', values=['东四', '天坛', '官园'])
aqi = data.swaplevel(axis='columns')['AQI'] #swaplevel转变层级
aqi.plot(backend='plotly') #多条折线图
aqi.plot(y='天坛', backend='plotly')

aqi = data.groupby(data.index.month).mean().swaplevel(axis='columns')['AQI']
aqi.plot.bar(
    backend='plotly', 
    barmode='group', #对变量分组
    height=500, # 图表高度
    width=800, # 图表宽度
    )#得到柱状图
aqi.T.plot.bar(
    backend='plotly', 
    height=500, # 图表高度
    width=800, # 图表宽度
    ) #叠起来

 看到了一篇写的很全的文章,也可参考

(3条消息) pandas学习笔记_雨落GJS的博客-优快云博客_pandas学习笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值