目录
pandas
是 Python 的一个开源数据分析库,提供了高效、灵活且快速的数据结构,尤其适合于结构化数据的清洗、处理、分析和可视化。其核心数据结构是 Series
和 DataFrame
。
Series
:
一维的带标签的数组,可以保存任何数据类型(整数、字符串、浮点数、Python 对象等)。DataFrame
:
二维的带标签的数据结构。可以看作是多个 Series 的组合。
Series
Series
是 pandas
库中的一个基本数据结构。它是一个一维的带标签的数组,可以包含任何数据类型(整数、浮点数、字符串、Python 对象等)。Series
可以被看作是一个定长的有序字典,因为它是标签到数据值的一个映射。
创建 Series
从列表创建
import pandas as pd
s = pd.Series([1, 2, 3, 4])
print(s)
# 输出:
# 0 1
# 1 2
# 2 3
# 3 4
# dtype: int64
使用自定义索引
s = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
print(s)
# 输出:
# a 1
# b 2
# c 3
# d 4
# dtype: int64
从字典创建
data = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
s = pd.Series(data)
print(s)
# 输出:
# a 1
# b 2
# c 3
# d 4
# dtype: int64
Series 的属性和方法
索引和值
s = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
print(s.index) # 输出: Index(['a', 'b', 'c', 'd'], dtype='object')
print(s.values) # 输出: array([1, 2, 3, 4])
访问元素
print(s['a']) # 输出: 1
print(s[['a', 'c']])
# 输出:
# a 1
# c 3
# dtype: int64
条件选择
print(s[s > 2])
# 输出:
# c 3
# d 4
# dtype: int64
数学运算
print(s + 5)
# 输出:
# a 6
# b 7
# c 8
# d 9
# dtype: int64
检查缺失值
s = pd.Series([1, 2, 3, None])
print(s.isnull())
# 输出:
# 0 False
# 1 False
# 2 False
# 3 True
# dtype: bool
应用函数
import numpy as np
s = pd.Series([1, 2, 3, 4])
print(s.apply(np.log))
# 输出:
# 0 0.000000
# 1 0.693147
# 2 1.098612
# 3 1.386294
# dtype: float64
Series
是 pandas
的核心组件之一,与 DataFrame
一起,为数据操作和分析提供了强大的功能。更多功能请参考官网pandas: Series
Dataframe
DataFrame
是 pandas
库中的另一个核心数据结构。它是一个二维的、大小可变的、具有潜在异质类型的表格数据结构。简单地说,DataFrame
可以被看作是一个电子表格或 SQL 表,或 Series
对象的字典集合。
创建 DataFrame
从字典创建
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'San Francisco', 'Los Angeles']
}
df = pd.DataFrame(data)
'''
Name Age City
0 Alice 25 New York
1 Bob 30 San Francisco
2 Charlie 35 Los Angeles
'''
从列表的列表创建
data = [['Alice', 25, 'New York'], ['Bob', 30, 'San Francisco'], ['Charlie', 35, 'Los Angeles']]
df = pd.DataFrame(data, columns=['Name', 'Age', 'City'])
DataFrame 的属性和方法
查看数据
print(df.head(2)) # 查看前两行
print(df.tail(2)) # 查看最后两行
获取列、行、和值
print(df.columns) # 获取列名 df.columns.tolist() = ['Name', 'Age', 'City']
print(df.index) # 获取行索引df.index.tolist() = [0,1,2]
print(df.values) # 获取值
'''
Index(['Name', 'Age', 'City'], dtype='object')
RangeIndex(start=0, stop=3, step=1)
[['Alice' 25 'New York']
['Bob' 30 'San Francisco']
['Charlie' 35 'Los Angeles']]
'''
选择数据
print(df['Name']) # 选择 'Name' 列
'''
0 Alice
1 Bob
2 Charlie
'''
print(df[['Name', 'City']]) # 选择多列
'''
Name: Name, dtype: object
Name City
0 Alice New York
1 Bob San Francisco
2 Charlie Los Angeles
'''
print(df.iloc[0]) # 选择第一行
print(df.iloc[0].values) # 选择第一行,并返回numpy.ndarray的数据
print(df.loc[0:1]) # 选择第一行和第二行
print(df.loc[0:1,'Name'] # 选择第一行和第二行并且列名为Name的数据
条件筛选
import pandas as pd
# 创建示例数据
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
'Age': [25, 30, 35, 40, 45],
'Salary': [50000, 55000, 60000, 65000, 70000]
}
df = pd.DataFrame(data)
# 执行筛选操作
'''
选择年龄大于30的所有人。
选择薪水在$55000到$65000之间的所有人。
选择名字以"C"开头的所有人。
选择年龄小于40且薪水大于$50000的所有人。
'''
results = {
"1. Age > 30": df[df['Age'] > 30],
"2. 55000 <= Salary <= 65000": df[(df['Salary'] >= 55000) & (df['Salary'] <= 65000)],
"3. Names starting with 'C'": df[df['Name'].str.startswith('C')],
"4. Age < 40 and Salary > 50000": df[(df['Age'] < 40) & (df['Salary'] > 50000)]
}
设置索引
在Pandas中,DataFrame是一个二维的、大小可变的、可以存储各种类型数据的表格。每个DataFrame都有行和列,行通常有一个特殊的列称为索引。你可以设置任何一列作为这个索引。因为索引是比较重要的,所以详细介绍下
以下是如何设置DataFrame的索引的一些基本方法:
使用现有的列作为索引
参数inplace决定是否在原数据上进行修改,如果设置为False, 则不会在在原数据上修改,而是返回一个修改后的,新的DataFrame
。
df.set_index('column_name', inplace=True)
重置索引
如果你想重置索引并将当前索引作为DataFrame的一列,“重置索引”是指将当前的索引删除,并重新为DataFrame或Series分配一个默认的整数索引(从0开始的递增整数)。可以使用:
df.reset_index(inplace=True) #
创建一个新的索引
可以直接为DataFrame分配一个新的索引:
df.index = new_index_list
使用多个列作为多级索引
df.set_index(['column1', 'column2'], inplace=True)
设置索引时删除原索引列
默认情况下,set_index
会保留原索引列。如果不想保留原索引列,可以这样做:
df.set_index('column_name', drop=True, inplace=True)
设置索引时添加新的索引列
如果想在设置索引的同时将原索引作为一个新的列,可以这样做:
df.set_index('column_name', append=True, inplace=True)
下面通过一个简单的示例来看一下如何在实践中应用这些方法:在上面的示例中,我们创建了一个简单的DataFrame
,并使用列 ‘C’ 作为索引。现在,你可以看到索引已经更改为列 ‘C’ 的值。
import pandas as pd
# 创建一个示例DataFrame
data = {
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': ['p', 'q', 'r']
}
df = pd.DataFrame(data)
# 使用列'C'作为索引
df.set_index('C', inplace=True)
'''
A B
C
p 1 4
q 2 5
r 3 6
'''
排序
df.sort_values(by='Age', ascending=False) # 按年龄降序排序
统计方法
print(df.describe()) # 描述性统计
print(df.mean()) # 平均值 默认为列平均值axis=0; df.mean(axis=1)为行平均值
print(df.median()) # 中位数
应用函数
df['Age'] = df['Age'].apply(lambda x: x + 1) # 每个人的年龄增加1
处理缺失数据
df.dropna() # 删除含有 NaN 的行
df.fillna(0) # 用 0 填充 NaN
添加 删除 插入 合并数据
#添加列
df['new_column'] = new_data
#添加行
new_row = pd.Series(data, index=df.columns)
df = df.append(new_row, ignore_index=True)
# 删除列
df = df.drop(columns=['column_name'])
# 删除行:可以通过指定标签名和相应的轴,或者直接使用索引删除行。
df = df.drop(index=row_index)
# 插入列:loc是整数,loc=1,在第0列后面插入
df.insert(loc, 'column_name', values)
# 水平串联合并两个或者多个DataFrame
result = pd.concat([df1, df2], axis=1)
# 垂直串联合并两个或者多个DataFrame
result = pd.concat([df1, df2], axis=0) # 垂直合并
# 基于共同列的值来合并两个DataFrame
# 在同一个列中,相同值的整行被保留,其他的被丢弃
result = pd.merge(df1, df2, on='common_column')
# 基于索引来合并
result = df1.join(df2)
在这里,特别的说明一下join
方法。join()
方法是另一种在 pandas 中合并 DataFrames 的方法,但它主要基于索引来进行合并,而不是列。join()
的默认行为是执行左连接(how='left'
),这意味着它会保留调用 join
方法的 DataFrame(左侧)的所有行,并添加另一个 DataFrame(右侧)的匹配行。
result = left_df.join(right_df, on=keys, how='left')
left_df
是调用join
方法的 DataFrame。right_df
是你要连接的其他 DataFrame。keys
是右侧 DataFrame 的列,这些列将与左侧 DataFrame 的索引进行匹配。how
参数决定了连接的类型(例如 ‘left’, ‘right’, ‘outer’, ‘inner’)。
下面使用一个示例来说明 join
方法:
在上述示例中,我们创建了两个 DataFrame:left_df
和 right_df
。它们都有索引 'K0', 'K1', 'K2'
,但 right_df
还有额外的索引 'K3'
。
当我们使用 join()
方法合并这两个 DataFrame 时,以下是我们观察到的:
- 对于索引
'K0'
和'K2'
,它们在两个 DataFrame 中都存在,所以它们的所有列都包含在结果中。 - 对于索引
'K1'
,它只在left_df
中存在,因此结果中对应的right_df
的列都是NaN
。 - 尽管索引
'K3'
存在于right_df
中,但由于我们使用了左连接(left join),并且它不存在于left_df
中,所以它不包含在结果中。
另外,当使用how='right'
时,结果正好与上述相反,K1
被丢弃,'K3'
仍存在;当使用how='outer'
时,所有索引都存在,没有数据的地方用NaN
填充;当使用how='inner'
时,只有索引 'K0'
和 'K2'
所在的行存在。
join()
方法是一个强大的工具,特别是当想基于索引而不是列值来合并数据时。
分组
grouped = df.groupby('City')
print(grouped.get_group('New York')) # 获取'City'列中所有New York所在的行的数据,
透视表
pivot = df.pivot_table(values='Age', index='City', aggfunc='mean') # 按城市分组,计算平均年龄
读写数据
df.to_csv('data.csv', index=False) # 写入 CSV 文件
dataframe = pd.read_csv('data.csv') # 从 CSV 文件读取
除了 CSV 外,以下是一些常见的文件格式及其相应的读写方法:
-
Excel:
- 读取:
pd.read_excel('filename.xlsx', sheet_name='Sheet1')
- 写入:
df.to_excel('filename.xlsx', sheet_name='Sheet1')
- 读取:
-
SQL 数据库:
- 读取:
pd.read_sql(query, connection_object)
- 写入:
df.to_sql('table_name', connection_object)
- 读取:
-
HDF5 (层次型数据格式):
- 读取:
pd.read_hdf('filename.h5', 'key')
- 写入:
df.to_hdf('filename.h5', 'key')
- 读取:
-
Parquet (一种列式存储格式):
- 读取:
pd.read_parquet('filename.parquet')
- 写入:
df.to_parquet('filename.parquet')
- 读取:
-
Msgpack (一种二进制格式):
- 读取:
pd.read_msgpack('filename.msg')
- 写入:
df.to_msgpack('filename.msg')
- 读取:
-
Stata:
- 读取:
pd.read_stata('filename.dta')
- 写入:
df.to_stata('filename.dta')
- 读取:
-
SAS:
- 读取:
pd.read_sas('filename.sas7bdat')
- 读取:
-
Feather (轻量级的列式存储格式):
- 读取:
pd.read_feather('filename.feather')
- 写入:
df.to_feather('filename.feather')
- 读取:
-
Pickle (Python 对象序列化格式):
- 读取:
pd.read_pickle('filename.pkl')
- 写入:
df.to_pickle('filename.pkl')
- 读取:
-
JSON:
- 读取:
pd.read_json('filename.json')
- 写入:
df.to_json('filename.json')
- 读取:
-
HTML:
- 读取:
pd.read_html('filename.html')
- 写入:
df.to_html('filename.html')
- 读取:
这些函数通常都有很多额外的参数,允许微调数据的导入和导出,如指定分隔符、设置编码、选择特定的列或行等。请注意,为了使用某些格式(如 Excel, SQL, Parquet 等),可能需要安装额外的库或驱动。
这只是 DataFrame
功能的简短概述。pandas
的 DataFrame
提供了大量的方法和属性,使其成为数据处理和分析的强大工具。更多DataFrame\的功能请参考官网 DataFrame