在后台回复【阅读书籍】
即可获取python相关电子书~
Hi,我是山月。
上次给大家分享了pandas的基础知识:Python自动化办公:pandas入门教程。有没有学起来呢~
今天主要来给大家粗略的介绍下操作pandas和excel表格的几个区别,希望能给大家一些帮助。
01
数据结构
通用术语:
1、DataFrame
pandas 中的 DataFrame 类似于 Excel 的工作表。
但是Excel 工作簿可以包含多个工作表,而 pandas DataFrame 是独立存在的。
2、Series
Series 表示 DataFrame 的一列数据结构,使用Series类似于引用电子表格的一列。
3、Index
每个 DataFrame 和 Series 都有一个Index,它是数据行上的标签。
在 pandas 中,如果未指定索引,则默认使用 RangeIndex(第一行 = 0,第二行 = 1,依此类推),类似于电子表格中的行号(数字)。
pandas 也可以将索引设置为一个(或多个)唯一值,这就像在工作表中拥有一个用作行标识符的列。
索引值是固定的,所以如果对 DataFrame 中的行重新排序,行的标签也不会改变。
02
输入/输出数据
Excel 可以通过双击或者右键选择“打开”菜单打开各种格式的表格文件,然后可以直接在单元格中输入值。
Pandas可以通过字典或者读取外部数据的方法来构建DataFrame 。
一般值少的话是通过字典来构建,其中键是列名,值是数据:
import pandas as pd
df = pd.DataFrame({"x": [1, 3, 5], "y": [2, 4, 6]})
print(df)
'''
x y
0 1 2
1 3 4
2 5 6
'''
读取外部数据是通过.read_*()方法来读取不同格式的文件。
比如通过.read_csv()可以读取CSV格式的文件:
import pandaimport pandas as pd
csv_file = pd.read_csv("数据.csv")
print(csv_file)
'''
x y
0 1 2
1 3 4
2 5 6
'''
注意:pandas可以使用 DataFrame.head() 或 DataFrame.tail() 来选择要显示的数据行。
import pandas as pd
excel_df = pd.read_excel("数据.xls")
print('完整数据:')
print(excel_df)
print('前两行数据:')
print(excel_df.head(2))
print('后两行数据:')
print(excel_df.tail(2))
'''
完整数据:
x y
0 1 2
1 3 4
2 5 6
前两行数据:
x y
0 1 2
1 3 4
后两行数据:
x y
1 3 4
2 5 6
'''
Excel可以直接把数据保存为(另存为)不同格式(如.xls)的文件。
而pandas 是通过.to_*()方法来创建 Excel 、CSV 或其他格式文件的。
如把数据保存成.xls文件:
import pandas as pd
df = pd.DataFrame({"x": [1, 3, 5], "y": [2, 4, 6]})
df.to_excel("数据.xls", index=False) #index=False 时行索引标签不会保存在电子表格中
03
数据操作
在Excel中,可以在某个单元格中写入公式,然后将其拖到其他单元格中计算其他列的数据。
pandas 通过在 DataFrame 中指定单个Series来提供矢量化操作,也可以通过指定Series来分配新列。
而通过 DataFrame.drop() 方法可以从 DataFrame 中删除一列。
import pandas as pd
excel_df = pd.read_excel("数据.xls")
print("原始数据:")
print(excel_df)
excel_df["x"] = excel_df["x"] + 2 #x列的数据每个元素+2
excel_df["new_x"] = excel_df["x"] / 2 # 添加一个新列,数值为2列的数据的1/2
excel_df_drop = excel_df.drop(labels='y',axis=1,inplace=True) # 删除y列。
'''
inplace默认为False,表示该删除操作不改变原数据,而是返回一个执行删除操作后的新dataframe。
如需直接在原数据上进行删除操作,需要更改默认参数为 inplace=True
'''
print("更改后的数据:")
print(excel_df)
'''
原始数据:
x y
0 1 2
1 3 4
2 5 6
更改后的数据:
x new_x
0 3 1.5
1 5 2.5
2 7 3.5
'''
在 Excel 中,筛选是通过筛选图形菜单完成的:
DataFrames 可以通过多种方式筛选;其中最直观的是使用布尔索引。
import pandas as pd
excel_df = pd.read_excel("数据.xls")
print("原始数据:")
print(excel_df)
col_filtering = excel_df[excel_df["x"] > 2]
print("筛选出x大于2的数据:")
print(col_filtering)
'''
原始数据:
x y
0 1 2
1 3 4
2 5 6
筛选出x大于2的数据:
x y
1 3 4
2 5 6
'''
上面的条件语句是将一系列 True/False 对象传递给 DataFrame,然后返回所有为 True 的行。
import pandas as pd
excel_df = pd.read_excel("数据.xls")
print("原始数据:")
print(excel_df)
is_3 = excel_df["x"] == 3
print('判断x列值是否等于3:')
print(is_3)
print('统计x列值等于3的个数:')
print(is_3.value_counts())
print('打印x列值等于3的行:')
print(excel_df[is_3])
'''
原始数据:
x y
0 1 2
1 3 4
2 5 6
3 1 2
4 3 4
5 5 6
判断x列值是否等于3:
0 False
1 True
2 False
3 False
4 True
5 False
Name: x, dtype: bool
统计x列值等于3的个数:
False 4
True 2
Name: x, dtype: int64
打印x列值等于3的行:
x y
1 3 4
4 3 4
'''
假设我们要根据 x 列的数据来创建一个值为 low(< 3) 或 high(≥3) 的存储列。
在Excel中,我们可以使用条件公式进行逻辑比较。
我们将在C2单元格写入公式【 =IF(A2 < 3, "low", "high")】 ,然后将其拖动以填充新存储列中的所有单元格。
在 pandas 中,我们可以使用 numpy 中的 where 方法完成相同的操作。
import pandas as pd
import numpy as np
excel_df = pd.read_excel("数据.xls")
print("原始数据:")
print(excel_df)
excel_df["bucket"] = np.where(excel_df["x"] < 3, "low", "high")
print('新建一列x值和3的比较结果:')
print(excel_df)
'''
原始数据:
x y
0 1 2
1 3 4
2 5 6
3 1 2
4 3 4
5 5 6
新建一列x值和3的比较结果:
x y bucket
0 1 2 low
1 3 4 high
2 5 6 high
3 1 2 low
4 3 4 high
5 5 6 high
'''
我们可以将日期功能分为两部分:解析和输出。
在Excel中,通常会自动解析日期值,但如果需要,也可以使用 DATEVALUE 函数。
在 pandas 中,需要在从 外部文档中(如CSV文件) 读取时或在 DataFrame 中将纯文本显式转换为日期时间对象。
解析后,Excel会以默认格式显示日期,但可以更改格式。而在 pandas 中,一般在使用它们进行计算时将日期保留为datetime对象。
如果想输出部分日期(例如年份)可以是通过Excel中的日期函数和 pandas 中的datetime属性来完成。
如给定Excel的 A 列和 B 列中的 date1 和 date2后,你可以通过以下公式来进行日期操作:
等效的 pandas 操作如下所示:
import pandas as pd
df = pd.DataFrame(
{
"date1": ["2013-01-15"],
"date2": ["2015-02-15"],
}
)
# 把日期转成datetime对象
df["date1"] = pd.to_datetime(df["date1"])
df["date2"] = pd.to_datetime(df["date2"])
# 利用datetime属性进行日期操作
df["date1_year"] = df["date1"].dt.year
df["date2_month"] = df["date2"].dt.month
df["date1_next"] = df["date1"] + pd.offsets.MonthBegin()
df["months_between"] = df["date2"].dt.to_period("M") - df["date1"].dt.to_period("M")
print(df)
'''
date1 date2 date1_year date2_month date1_next months_between
0 2013-01-15 2015-02-15 2013 2 2013-02-01 <25 * MonthEnds>
'''
在Excel中,你可以通过以下方式选择所需的列:
隐藏列
删除列
将单元格区域从一个工作表引用到另一个工作表
由于Excel的列通常在标题行中命名,因此重命名列只需更改第一个单元格中的文本即可。
下面看看如何在 pandas 中进行相同的操作。
1、保留列
import pandas as pd
excel_df = pd.read_excel("数据.xls")
print("原始数据:")
print(excel_df)
x_df = excel_df[["x"]]
print("只保留x列数据:")
print(x_df)
'''
原始数据:
x y
0 1 2
1 3 4
2 5 6
3 1 2
4 3 4
5 5 6
只保留x列数据:
x
0 1
1 3
2 5
3 1
4 3
5 5
'''
2、删除一列
import pandas as pd
excel_df = pd.read_excel("数据.xls")
print("原始数据:")
print(excel_df)
excel_df.drop("x", axis=1,inplace=True)
print("删除x列后:")
print(excel_df)
'''
原始数据:
x y
0 1 2
1 3 4
2 5 6
3 1 2
4 3 4
5 5 6
删除x列后:
y
0 2
1 4
2 6
3 2
4 4
5 6
'''
3、重命名列
import pandas as pd
excel_df = pd.read_excel("数据.xls")
print("原始数据:")
print(excel_df)
excel_df.rename(columns={"x": "x_2"},inplace=True)
print("重命名x列:")
print(excel_df)
'''
原始数据:
x y
0 1 2
1 3 4
2 5 6
3 1 2
4 3 4
5 5 6
重命名x列:
x_2 y
0 1 2
1 3 4
2 5 6
3 1 2
4 3 4
5 5 6
'''
Excel中的排序可以直接选择【升序】、【降序】进行排序,也可以通过排序对话框完成:
pandas 有一个 DataFrame.sort_values() 方法可以用来进行排序。
import pandas as pd
excel_df = pd.read_excel("数据.xls")
print("原始数据:")
print(excel_df)
excel_df = excel_df.sort_values(["x", "y"])
print("先按x列数据后按y列数据排序:")
print(excel_df)
'''
原始数据:
x y
0 5 8
1 5 6
2 9 10
3 9 12
4 1 4
5 1 2
先按x列数据后按y列数据排序:
x y
5 1 2
4 1 4
1 5 6
0 5 8
2 9 10
3 9 12
'''
04
字符串处理
在Excel中,可以使用 LEN 函数找到文本中的字符数。
这可以与 TRIM 函数一起使用,TRIM函数主要功能是:除了单词之间的单个空格外,清除文本中所有的空格。
在pandas中可以使用 Series.str.len() 找到字符串的长度,并可以使用 rstrip 来排除尾随空格。
import pandas as pd
df = pd.DataFrame(
{
"data": [" 我 是山月 ", "我 是山月"],
}
)
print("原始数据:")
print(df)
df_len = df["data"].str.len()
print("字符串长度:")
print(df_len)
df_len_rstrip = df["data"].str.rstrip().str.len()
print("删除尾随空格后的字符串长度:")
print(df_len_rstrip)
'''
原始数据:
data
0 我 是山月
1 我 是山月
字符串长度:
0 7
1 5
Name: data, dtype: int64
删除尾随空格后的字符串长度:
0 6
1 5
Name: data, dtype: int64
'''
Excel的FIND 函数可以返回第一个匹配到子字符串的位置,从1开始。
Pandas中可以使用 Series.str.find() 方法在一列字符串中查找子字符的第一个匹配位置。
如果找到子字符串,则该方法返回其位置(从0开始)。如果未找到,则返回 -1。
import pandas as pd
df = pd.DataFrame(
{
"sex": ["male", "femle"],
"name": ["Jack", "Maria"],
}
)
print("原始数据:")
print(df)
df_find = df["sex"].str.find("em")
print("查找字符em的第一个匹配位置:")
print(df_find)
'''
原始数据:
sex name
0 male Jack
1 femle Maria
查找字符em的第一个匹配位置:
0 -1
1 1
Name: sex, dtype: int64
'''
Excel有一个 MID 函数,作用是从一个字符串中截取出指定数量的字符。如获取字符串的第一个字符:
=MID(A2,1,1)
对于 pandas,可以使用 [] 按位置从字符串中提取子字符串。注意,Python 的索引是从0开始的。
import pandas as pd
df = pd.DataFrame(
{
"sex": ["male", "femle"],
"name": ["Jack", "Maria"],
}
)
print("原始数据:")
print(df)
df_first_str = df["sex"].str[0:1]
print("提取sex列数据的第一个字符:")
print(df_first_str)
'''
原始数据:
sex name
0 male Jack
1 femle Maria
提取sex列数据的第一个字符:
0 m
1 f
Name: sex, dtype: object
'''
在 Excel 中,可以使用【分列】来拆分文本和检索特定列。(请注意,也可以通过公式来做到这一点。)
在 pandas 中提取单词的最简单方法是按空格分割字符串,然后按索引引用单词。
import pandas as pd
df = pd.DataFrame(
{
"name": ["John Smith", "Jane Cook"],
}
)
print("原始数据:")
print(df)
df["First_Name"] = df["name"].str.split(" ", expand=True)[0]
df["Last_Name"] = df["name"].str.rsplit(" ", expand=True)[1]
print("以提取到的单词作为新列:")
print(df)
'''
原始数据:
name
0 John Smith
1 Jane Cook
以提取到的单词作为新列:
name First_Name Last_Name
0 John Smith John Smith
1 Jane Cook Jane Cook
'''
Excel提供了 UPPER、LOWER 和 PROPER 函数,用于将文本分别转换为大写、小写和首字母大写。
等效的 pandas 方法是 Series.str.upper()、Series.str.lower() 和 Series.str.title()。
import pandas as pd
df = pd.DataFrame(
{
"name": ["John smith", "Jane cook"],
}
)
print("原始数据:")
print(df)
df["upper"] = df["name"].str.upper()
df["lower"] = df["name"].str.lower()
df["title"] = df["name"].str.title()
print("以转换后的数据作为新列:")
print(df)
'''
原始数据:
name
0 John smith
1 Jane cook
以转换后的数据作为新列:
name upper lower title
0 John smith JOHN SMITH john smith John Smith
1 Jane cook JANE COOK jane cook Jane Cook
'''
05
合并
在 Excel 中,可以通过 VLOOKUP 协助完成表格的合并,不过比较傻瓜,手动的地方较多。
而 DataFrames 有一个 merge() 方法,它提供了类似的功能,其中不同的连接类型可以通过关键字how完成。
how = 'inner':默认值,内连接,只合并两个表格都有的行
how = 'left':左连接,只合并在第一个表格里有的行,第二个表格里没有这行数据的用NaN填充
how = 'right':右连接,只合并在第二个表格里有的行,第一个表格里没有这行数据的用NaN填充
how = 'outer':外连接,合并两个表格里所有的行,没有数据的用NaN填充
实例:
import pandas as pd
import numpy as np
df1 = pd.DataFrame({"key": ["A", "B", "C", "D"], "value": np.random.randn(4)})
df2 = pd.DataFrame({"key": ["B", "D", "D", "E"], "value": np.random.randn(4)})
print("df1原始数据:")
print(df1)
print("df2原始数据:")
print(df2)
inner_join = df1.merge(df2, on=["key"], how="inner")
print("内连接:")
print(inner_join)
left_join = df1.merge(df2, on=["key"], how="left")
print("左连接:")
print(left_join)
right_join = df1.merge(df2, on=["key"], how="right")
print("右连接:")
print(right_join)
outer_join = df1.merge(df2, on=["key"], how="outer")
print("外连接:")
print(outer_join)
'''
df1原始数据:
key value
0 A 0.622766
1 B -0.656180
2 C 0.519211
3 D 1.070338
df2原始数据:
key value
0 B -0.025094
1 D -1.380452
2 D -0.273305
3 E -0.990598
内连接:
key value_x value_y
0 B -0.656180 -0.025094
1 D 1.070338 -1.380452
2 D 1.070338 -0.273305
左连接:
key value_x value_y
0 A 0.622766 NaN
1 B -0.656180 -0.025094
2 C 0.519211 NaN
3 D 1.070338 -1.380452
4 D 1.070338 -0.273305
右连接:
key value_x value_y
0 B -0.656180 -0.025094
1 D 1.070338 -1.380452
2 D 1.070338 -0.273305
3 E NaN -0.990598
外连接:
key value_x value_y
0 A 0.622766 NaN
1 B -0.656180 -0.025094
2 C 0.519211 NaN
3 D 1.070338 -1.380452
4 D 1.070338 -0.273305
5 E NaN -0.990598
'''
06
其他
在Excel中,如果你想在一组单元格中按照一组模式创建一系列数字,可以在输入前2~3个数字后通过拖动来填充序列。
在Pandas中可以通过创建一个系列并将其分配给所需的单元格来实现。
import pandas as pd
df = pd.DataFrame({"AAA": [1] * 8, "BBB": list(range(0, 8))})
print("原始数据:")
print(df)
series = list(range(1, 5))
print('series的值是:%s'%series)
df.loc[2:5, "AAA"] = series
print("更改后:")
print(df)
'''
原始数据:
AAA BBB
0 1 0
1 1 1
2 1 2
3 1 3
4 1 4
5 1 5
6 1 6
7 1 7
series的值是:[1, 2, 3, 4]
更改后:
AAA BBB
0 1 0
1 1 1
2 1 2
3 2 3
4 3 4
5 4 5
6 1 6
7 1
Excel 具有删除重复值的内置功能:
这在 pandas 中通过 drop_duplicates() 得到支持。
import pandas as pd
df = pd.DataFrame(
{
"class": ["A", "A", "A", "B", "B", "D"],
"count": [42, 35, 42, 50, 50, 45],
"pass": ["Yes", "Yes", "Yes", "Yes", "No", "Yes"],
}
)
print("原始数据:")
print(df)
df2 = df.drop_duplicates()
print('删除重复行:')
print(df2)
df3 = df.drop_duplicates(["class", "count"])
print("删除指定列之间的重复行:")
print(df3)
'''
原始数据:
class count pass
0 A 42 Yes
1 A 35 Yes
2 A 42 Yes
3 B 50 Yes
4 B 50 No
5 D 45 Yes
删除重复行:
class count pass
0 A 42 Yes
1 A 35 Yes
3 B 50 Yes
4 B 50 No
5 D 45 Yes
删除指定列之间的重复行:
class count pass
0 A 42 Yes
1 A 35 Yes
3 B 50 Yes
5 D 45 Yes
'''
Excel中的数据透视表可以通过重塑和数据透视表在 pandas 中实现。
在 Excel 中,我们对数据透视表使用以下配置:
pandas中的等价操作:
import pandas as pd
import numpy as np
df = pd.DataFrame(
{
"total_bill": [16.99,10.34,21.01,23.68,24.59,29.03,27.18,22.67,17.82,18.78],
"tip": [1.01,1.66,3.5,3.31,3.61,5.92,2,2,1.75,3],
"sex": ["Female","Male","Male","Male","Female","Male","Female","Male","Male","Female"],
"smoker": ["No","No","No","No","No","No","Yes","Yes","No","No"],
"day": ["Sun","Sun","Sun","Sun","Sun","Sat","Sat","Sat","Sat","Thur"],
"time": ["Dinner","Dinner","Dinner","Dinner","Dinner","Dinner","Dinner","Dinner","Dinner","Dinner"],
"size": [2,3,3,2,4,3,2,2,2,2],
}
)
print("原始数据:")
print(df)
df_pivot_table = pd.pivot_table(
df, values="tip", index=["size"], columns=["sex"], aggfunc=np.average
)
print("数据透视表:")
print(df_pivot_table)
'''
原始数据:
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
5 29.03 5.92 Male No Sat Dinner 3
6 27.18 2.00 Female Yes Sat Dinner 2
7 22.67 2.00 Male Yes Sat Dinner 2
8 17.82 1.75 Male No Sat Dinner 2
9 18.78 3.00 Female No Thur Dinner 2
数据透视表:
sex Female Male
size
2 2.003333 2.353333
3 NaN 3.693333
4 3.610000 NaN
'''
Excel的添加一行就不多说了。
对于Pandas,假设我们使用的是 RangeIndex(编号为 0、1 等),我们可以使用 concat() 在 DataFrame 的底部添加一行。
import pandas as pd
df = pd.DataFrame(
{
"class": ["A", "A", "A", "B", "B", "D"],
"count": [42, 35, 42, 50, 50, 45],
"pass": ["Yes", "Yes", "Yes", "Yes", "No", "Yes"],
}
)
print("原始数据:")
print(df)
new_row = pd.DataFrame([["E", 51, True]],
columns=["class", "count", "pass"])
df2 = pd.concat([df, new_row])
print("添加一行后的数据:")
print(df2)
'''
原始数据:
class count pass
0 A 42 Yes
1 A 35 Yes
2 A 42 Yes
3 B 50 Yes
4 B 50 No
5 D 45 Yes
添加一行后的数据:
class count pass
0 A 42 Yes
1 A 35 Yes
2 A 42 Yes
3 B 50 Yes
4 B 50 No
5 D 45 Yes
0 E 51 True
'''
Excel 提供了【查找】、【替换】对话框来逐个找到匹配的单元格,或者进行替换。
在 pandas 中,这个操作通常是通过条件表达式一次对整个列或 DataFrame 完成的。
import pandas as pd
df = pd.DataFrame(
{
"class": ["A", "A", "A", "B", "B", "D"],
"count": [42, 35, 42, 50, 50, 45],
"pass": ["Yes", "Yes", "Yes", "Yes", "No", "Yes"],
}
)
print("原始数据:")
print(df)
print("df里字符串为A的返回True:")
print(df == "A")
print("pass列是否包含Y:")
print(df["pass"].str.contains("Y"))
'''
原始数据:
class count pass
0 A 42 Yes
1 A 35 Yes
2 A 42 Yes
3 B 50 Yes
4 B 50 No
5 D 45 Yes
df里字符串为A的返回True:
class count pass
0 True False False
1 True False False
2 True False False
3 False False False
4 False False False
5 False False False
pass列是否包含Y:
0 True
1 True
2 True
3 True
4 False
5 True
Name: pass, dtype: bool
'''
pandas 的 replace() 可与 Excel 的全部替换相媲美。
import pandas as pd
df = pd.DataFrame(
{
"class": ["A", "A", "A", "B", "B", "D"],
"count": [42, 35, 42, 50, 50, 45],
"pass": ["Yes", "Yes", "Yes", "Yes", "No", "Yes"],
}
)
print("原始数据:")
print(df)
df2 = df.replace("Yes", "Y")
print("把Yes替换成Y:")
print(df2)
'''
原始数据:
class count pass
0 A 42 Yes
1 A 35 Yes
2 A 42 Yes
3 B 50 Yes
4 B 50 No
5 D 45 Yes
把Yes替换成Y:
class count pass
0 A 42 Y
1 A 35 Y
2 A 42 Y
3 B 50 Y
4 B 50 No
5 D 45 Y
'''
好啦,今天的内容就到这。
如果喜欢山月的分享方式的话,点点手指头关注山月哦~
END
您的“点赞”、“在看”和 “分享”是我们产出的动力。