最近经常看到各平台里都有Python的广告,都是对excel的操作,这里明哥收集整理了一下pandas对excel的操作方法和使用过程。本篇介绍 pandas 的 DataFrame
对列 (Column) 的处理方法。示例数据请通过明哥的gitee进行下载。
增加计算列
pandas 的 DataFrame
,每一行或每一列都是一个序列 (Series
)。比如:
import pandas as pd df1 = pd.read_excel('./excel-comp-data.xlsx');
此时,用 type(df1['city']
,显示该数据列(column)的类型是 pandas.core.series.Series
。理解每一列都是 Series
非常重要,因为 pandas 基于 numpy,对数据的计算都是整体计算。深刻理解这个,才能理解后面要说的诸如 apply()
函数等。
如果列名 (column name)没有空格,则列有两种方式表达:
df1['city'] df1.city
如果列名有空格,或者创建新列(即该列不存在,需要创建,第一次使用的变量),则只能用第一种表达式。
假设我们要对三个月的数据进行汇总,可以使用下面的方法。实际上就是创建一个新的数据列:
# 由于是创建,不能使用 df.Total df1['Total'] = df1['Jan'] + df1['Feb'] + df1['Mar']
df1['Jan']
到 df1['Mar']
都是 Series
,所以使用 +
号,可以得到三个 Series
对应位置的数据合计。
当然,也可以用下面的方式:
df1['total'] = df1.Jan + df1.Feb + df1.Mar
增加条件计算列
假设现在要根据合计数 (Total 列),当 Total 大于 200,000 ,类别为 A,否则为 B。在 Excel 中实现用的是 IF
函数,但在 pandas 中需要用到 numpy 的 where
函数:
df1['category'] = np.where(df1['total'] > 200000, 'A', 'B')
在指定位置插入列
上面方法增加的列,位置都是放在最后。如果想要在指定位置插入列,要用 dataframe.insert()
方法。假设我们要在 state
列后面插入一列,这一列是 state
的简称 (abbreviation)。在 Excel 中,根据 state 来找到 state 的简称 ,一般用 VLOOKUP
函数。我们用两种方法来实现,第一种方法,简称来自 Python 的 dict。
数据来源:
state_to_code = {"VERMONT": "VT", "GEORGIA": "GA", "IOWA": "IA", "Armed Forces Pacific": "AP", "GUAM": "GU", "KANSAS": "KS", "FLORIDA": "FL", "AMERICAN SAMOA": "AS", "NORTH CAROLINA": "NC", "HAWAII": "HI", "NEW YORK": "NY", "CALIFORNIA": "CA", "ALABAMA": "AL", "IDAHO": "ID", "FEDERATED STATES OF MICRONESIA": "FM", "Armed Forces Americas": "AA", "DELAWARE": "DE", "ALASKA": "AK", "ILLINOIS": "IL", "Armed Forces Africa": "AE", "SOUTH DAKOTA": "SD", "CONNECTICUT": "CT", "MONTANA": "MT", "MASSACHUSETTS": "MA", "PUERTO RICO": "PR", "Armed Forces Canada": "AE", "NEW HAMPSHIRE": "NH", "MARYLAND": "MD", "NEW MEXICO": "NM", "MISSISSIPPI": "MS", "TENNESSEE": "TN", "PALAU": "PW", "COLORADO": "CO", "Armed Forces Middle East": "AE", "NEW JERSEY": "NJ", "UTAH": "UT", "MICHIGAN": "MI", "WEST VIRGINIA": "WV", "WASHINGTON": "WA", "MINNESOTA": "MN", "OREGON": "OR", "VIRGINIA": "VA", "VIRGIN ISLANDS": "VI", "MARSHALL ISLANDS": "MH", "WYOMING": "WY", "OHIO": "OH", "SOUTH CAROLINA": "SC", "INDIANA": "IN", "NEVADA": "NV", "LOUISIANA": "LA", "NORTHERN MARIANA ISLANDS": "MP", "NEBRASKA": "NE", "ARIZONA": "AZ", "WISCONSIN": "WI", "NORTH DAKOTA": "ND", "Armed Forces Europe": "AE", "PENNSYLVANIA": "PA", "OKLAHOMA": "OK", "KENTUCKY": "KY", "RHODE ISLAND": "RI", "DISTRICT OF COLUMBIA": "DC", "ARKANSAS": "AR", "MISSOURI": "MO", "TEXAS": "TX", "MAINE": "ME"}
如果我们想根据 dict 的 key
找到对应的值,可以使用 dict.get()
方法,这个方法在找不到 key 的时候,不会抛出异常,只是返回 None。比如
state_to_code.get('TEXAS') # 返回 TX state_to_code.get('TEXASS') # 返回 None
dict.get()
方法参数为 key,是一个标量值。我们并不能像下面这样把整列都传给这个方法,比如下面这样:
df1['abbrev'] = state_to_code.get(df1['state'])
所以我们需要先构造一个 Series (abbrev)
,然后把 abbrev
赋值给 df1['abbrev']
:
abbrev = df1['state'].apply(lambda x: state_to_code.get(x.upper())) df1['abbrev'] = abbrev # 在后面插入列 df1.insert(6, 'abbr', abbrev) # 在指定位置插入列
apply()
函数值得专门写一篇,暂且不细说。
Vlookup 函数功能实现
实现类似 Excel 的 VLookup
功能,可以用 dataframe.merge()
方法。为此,需要将 state_to_code
这个 dict
的数据加载到 DataFrame
中。这里提供两种方法。
方法1: 把数据放在 excel 工作表中,然后读取 Excel 文件加载。数据如下:
excel_file = pd.ExcelFile('excel-comp-data.xlsx') df_abbrev = pd.read_excel(excel_file, sheetname = 'abbrev') df2 = df1.merge(df_abbrev, on='state') # 类似数据库的 inner join,不匹配数据不会显示
VLookup
函数根据位置来匹配,merge()
方法根据列名来匹配。因为上面语句中没有指定连接类型,不匹配的记录不会显示。如果需要将 df1
的数据全部显示出来,需要指定 merge()
方法的 how
参数:
df3 = df1.merge(df_abbrev, on='state', how='left') # 类似数据库的 left join
方法2:直接将 state_to_code
加载到 DataFrame
。但因为 state_to_code
全部是标量值 (scalar values),方法有一点不同,如下:
# 将 state_to_code 直接加载到 DataFrame abbr2 = pd.DataFrame(list(state_to_code.items()), columns=['state', 'abbr'])
计算合计数
假如需要对各个月份以及月份合计数进行求和。pandas 可以对 Series
运行 sum()
方法来计算合计:
import pandas as pd import numpy as np df = pd.read_excel('./excel-comp-data.xlsx'); df['Total'] = df.Jan + df.Feb + df.Mar # sum_row 的类型是 pandas.core.series.Series, Jan, Feb 等成为 Series 的 index sum_row = df[['Jan', 'Feb', 'Mar', 'Total']].sum()
也可以将 sum_row
转换成 DataFrame
, 以列的方式查看。DataFrame
的 T
方法实现行列互换。
# 转置变成 DataFrame df_sum = pd.DataFrame(data=sum_row).T df_sum
如果想要把合计数放在数据的下方,则要稍作加工。首先通过 reindex()
函数将 df_sum
变成与 df
具有相同的列,然后再通过 append()
方法,将合计行放在数据的后面:
# 转置变成 DataFrame df_sum = pd.DataFrame(data=sum_row).T # 将 df_sum 添加到 df df_sum = df_sum.reindex(columns=df.columns) # append 创建一个新的 DataFrame df_with_total = df.append(df_sum, ignore_index=True)
分类汇总
Excel 的分类汇总功能,在数据功能区,但因为分类汇总需要对数据进行排序,并且分类汇总的数据与明细数据混在一起,个人很少用到,分类汇总一般使用数据透视表。
而在 pandas 进行分类汇总,可以使用 DataFrame
的 groupby()
函数,然后再对 groupby()
生成的 pandas.core.groupby.DataFrameGroupBy
对象进行求和:
df_groupby = df[['state','Jan', 'Feb','Mar', 'Total']].groupby('state').sum() df_groupby.head()
数据格式化
pandas 默认的数据显示,没有使用千分位分隔符,在数据较大时,感觉不方便。如果需要对数据的显示格式化,可以自定义一个函数 number_format()
,然后对 DataFrame
运行 applymap(number_format)
函数。applymap()
函数对 DataFrame
中每一个元素都运行 number_format
函数。number_format
函数接受的参数必须为标量值,返回的也是标量值。
# 数字格式化 def number_format(x): return "{:,.0f}".format(x) # 使用逗号分隔,没有小数位 formated_df = df_groupby.applymap(number_format) formated_df.head()
数据透视表
pandas 运行数据透视表,使用 pivot_table()
方法。熟练使用 pivot_table()
需要一些练习。这里只是介绍最基本的功能:
- index 参数: 按什么条件进行汇总
- values 参数:对哪些数据进行计算
- aggfunc 参数:aggregation function,执行什么运算
# pivot table # pd.pivot_table 生成一个新的 DataFrame df_pivot = pd.pivot_table(df, index=['state'], values=['Jan','Feb','Mar','Total'], aggfunc= np.sum)
总结
Pandas可以对Excel进行基础的读写操作
Pandas可以实现对Excel各表各行各列的增删改查
Pandas可以进行表中列行筛选等
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]