Pandas 的两个主要的数据结构是 Series 和 DataFrame:
Series
是一维标记数组,类似于带有标签的列表。它可以包含不同类型的数据,并且可以通过索引进行访问和操作。DataFrame
是二维表格型数据结构,类似于 SQL 表或 Excel 电子表格。它由多个列组成,每列可以是不同类型的值。
Series
创建一维数组
直接创建
import pandas as pd
data = [1, 2, 3, 4, 5]
series = pd.Series(data)
print(series)
0 1
1 2
2 3
3 4
4 5
dtype: int64
指定索引
import pandas as pd
data = [10,20,30]
index_labels = ['a', 'b', 'c']
series = pd.Series(data, index=index_labels)
print(series)
a 10
b 20
c 30
dtype: int64
字典创建
import pandas as pd
data_dict = {'a':100,'b':200,'c':300}
series = pd.Series(data_dict)
print(series)
a 100
b 200
c 300
dtype: int64
修改 Series 对象的数据类型(dtype),可以使用 astype()
方法。astype() 方法允许将 Series 中的数据转换为指定的数据类型
索引和切片
- 使用整数位置索引
- 使用标签索引
- 使用布尔条件进行筛选
- 隐式整数位置索引: 默认情况下,Series 对象具有隐式的整数位置索引
import pandas as pd
data = [10, 20, 30, 40, 50]
index_labels = ['a', 'b', 'c','d','e']
s=pd.Series(data)[2] # 30
s=pd.Series(data)[2:4]
# 2 30
# 3 40
# dtype: int64
s=pd.Series(data,index=index_labels)['a'] #10
s=pd.Series(data,index=index_labels)['a':'c']
# a 10
# b 20
# c 30
# dtype: int64
x=pd.Series(data)
s=x[x<20]
# 0 10
# dtype: int64
x=pd.Series(data)
s=x.iloc[2] #30
s=x.iloc[2:4]
# 2 30
# 3 40
# dtype: int64
print(s)
查询索引和值:
s = pd.Series(data, index=index_labels)
print(s.index)
# Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
print(s.values)
# [10 20 30 40 50]
读取外部数据
import pandas as pd
# 读取CSV文件
df = pd.read_csv('data.csv')
# 打印数据框内容
print(df)
import pandas as pd
# 读取Excel文件,默认情况下将第一个工作表作为数据框
df = pd.read_excel('data.xlsx')
# 打印数据框内容
print(df)
DataFrame
创建
直接创建
import pandas as pd
df = pd.DataFrame()
索引
data = [['Alice', 25], ['Bob', 30], ['Charlie', 35]]
df = pd.DataFrame(data, columns=['Name', 'Age'])
字典
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie'], 'Age': [25, 30, 35]}
df = pd.DataFrame(data)
基本操作
访问列
# 使用列名访问单个列
name_column = df['Name']
# 使用点号访问单个列(仅适用于非保留关键字列名)
name_column = df.Name
# 访问多个列
subset_df = df[['Name', 'Age']]
访问行
# 使用iloc按索引位置访问单个行(基于0索引)
row_0 = df.iloc[0]
# 使用loc按标签名称访问单个行(基于标签索引)
row_alice = df.loc[df['Name'] == 'Alice']
# 根据条件筛选多行
subset_df = df[df['Age'] > 30]
添加新列:
df['City'] = ['New York', 'London', 'Paris']
删除列:
df = df.drop('Age', axis=1)
添加新行:
new_row = pd.Series(['Dave', 40], index=df.columns)
df = df.append(new_row, ignore_index=True)
删除行:
df = df.drop(0)
查询
info(): 提供有关DataFrame的基本信息,包括列名、非空值数量、每列的数据类型等。
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'London', 'Paris']}
df = pd.DataFrame(data)
df.info()
输出结果:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Name 3 non-null object
1 Age 3 non-null int64
2 City 3 non-null object
dtypes: int64(1), object(2)
memory usage: ... bytes
在上面的示例中,info()方法提供了有关DataFrame的基本信息。它显示了DataFrame中每个列的名称、非空值数量以及每列数据类型。
describe(): 提供有关数值列(int64或float64)的统计摘要信息,包括计数、均值、标准差、最小值、25%分位数、50%分位数(中位数)、75%分位数和最大值。
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'London', 'Paris']}
df = pd.DataFrame(data)
df.describe()
输出结果:
Age
count 3.000000
mean 30.000000
std 5.773503
min 25.000000
25% 27.500000
50% 30.000000
75% 32.500000
max 35.000000
head(): 显示DataFrame的前几行,默认显示前5行。
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
'Age': [25, 30, 35, 40, 45],
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Sydney']}
df = pd.DataFrame(data)
df.head()
输出结果:
Name Age City
0 Alice 25 New York
1 Bob 30 London
2 Charlie 35 Paris
3 David 40 Tokyo
4 Eva 45 Sydney
在上面的示例中,head()方法默认显示DataFrame的前5行。
如果你想要指定显示的行数,可以将所需的行数作为参数传递给head()方法。例如,如果你只想要显示前3行:
df.head(3)
输出结果:
Name Age City
0 Alice 25 New York
1 Bob 30 London
2 Charlie 35 Paris
tail(): 显示DataFrame的后几行,默认显示最后5行。
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
'Age': [25, 30, ,35, ,40, ,45],
,'City': ['New York', 'London', 'Paris', 'Tokyo', 'Sydney']}
df = pd.DataFrame(data)
df.tail()
输出结果:
Name Age City
0 Alice 25 New York
1 Bob 30 London
2 Charlie 35 Paris
3 David 40 Tokyo
4 Eva 45 Sydney
在上面的示例中,tail()方法默认显示DataFrame的最后5行。
同样,你也可以通过传递参数来指定显示的行数。例如,如果你只想要显示最后3行:
df.tail(3)
输出结果:
Name Age City
2 Charlie 35 Paris
3 David 40 Tokyo
4 Eva 45 Sydney
排序
使用sort_values()方法可以根据指定的列对DataFrame进行升序或降序排序,并且可以同时按照多个列进行排序。这使得你能够对数据进行灵活和定制化的排序操作
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'London', 'Paris']}
df = pd.DataFrame(data)
# 按照某一列进行升序排序
df_sorted = df.sort_values(by='Age')
print(df_sorted)
输出结果:
Name Age City
0 Alice 25 New York
1 Bob 30 London
2 Charlie 35 Paris
在上面的示例中,我们使用sort_values()方法按照Age列的值对DataFrame进行升序排序。
如果你想要按照多个列进行排序,可以将列名作为一个列表传递给by参数。例如,如果你想要先按照City列进行升序排序,然后再按照Age列进行降序排序:
df_sorted = df.sort_values(by=['City', 'Age'], ascending=[True, False])
print(df_sorted)
输出结果:
Name Age City
1 Bob 30 London
0 Alice 25 New York
2 Charlie 35 Paris
在上面的示例中,我们通过传递一个包含两个元素的列表给 by 参数来指定多个列,并使用 ascending 参数来指定每个列是否以升序或降序排序。
默认情况下,sort_values()方法会返回一个新的已排序的DataFrame,而不会修改原始的DataFrame。如果你想要在原始DataFrame上进行排序,可以使用inplace=True参数:
df.sort_values(by='Age', inplace=True)
print(df)
输出结果:
Name Age City
0 Alice 25 New York
1 Bob 30 London
2 Charlie 35 Paris
切片
- 切片行:
使用位置索引进行切片
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
'Age': [25, 30, 35, 40, 45],
'City': ['New York', 'London', 'Paris', 'Tokyo', 'Sydney']}
df = pd.DataFrame(data)
# 使用位置索引切片
df_slice = df[1:3]
print(df_slice)
输出结果:
Name Age City
1 Bob 30 London
2 Charlie 35 Paris
使用标签索引切片
df_slice = df.loc[1:3]
print(df_slice)
输出结果:
Name Age City
1 Bob 30 London
2 Charlie 35 Paris
3 David 40 Tokyo
在上面的示例中,我们使用了不同的方式对DataFrame进行行切片。使用位置索引进行切片时,起始位置是包含在内的,而结束位置是不包含在内的。而使用标签索引进行切片时,起始和结束都是包含在内的。
- 切片列:
使用列名进行切片:df[‘column_name’],其中 column_name 是要选择的列名。
使用多个列名进行切片:df[[‘column1’, ‘column2’]],其中 ‘column1’ 和 ‘column2’ 是要选择的多个列名。
使用单个列名切片
name_col = df['Name']
print(name_col)
输出结果:
0 Alice
1 Bob
2 Charlie
3 David
4 Eva
Name: Name, dtype: object
使用多个列名切片
name_age_cols = df[['Name', 'Age']]
print(name_age_cols)
输出结果:
Name Age
0 Alice 25
1 Bob 30
2 Charlie 35
3 David 40
4 Eva 45
在上面的示例中,我们使用了不同的方式对DataFrame进行了列切片。使用单个列名时,返回一个Series对象;使用多个列名时,返回一个新的DataFrame对象。
- 同时对行和列进行切片操作:
df_slice = df.loc[1:3, ['Name', 'Age']]
print(df_slice)
输出结果:
Name Age
1 Bob 30
2 Charlie 35
3 David 40
布尔索引
布尔索引基于一个条件表达式,返回一个与原始DataFrame形状相同的布尔值Series或DataFrame
- 使用比较运算符(如==、>、<、>=、<=等)创建一个布尔表达式,然后将其应用于DataFrame的列
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
'Age': [25, 30, 35, 40, 45],
'City': ['New York', 'London', 'Paris', 'Tokyo' ,'Sydney']}
df = pd.DataFrame(data)
# 使用比较运算符创建布尔表达式
bool_index = df['Age'] > 30
print(bool_index)
输出结果:
0 False
1 False
2 True
3 True
4 True
Name: Age, dtype: bool
将这个布尔表达式应用到DataFrame中以选择满足条件的行
# 使用布尔索引进行数据选择
selected_data = df[bool_index]
print(selected_data)
输出结果:
Name Age City
2 Charlie 35 Paris
3 David 40 Tokyo
4 Eva 45 Sydney
- 使用逻辑运算符(如&、|、~等)将多个布尔表达式组合起来
# 使用多个条件进行选择
bool_index = (df['Age'] > 30) & (df['City'] == 'London')
selected_data = df[bool_index]
print(selected_data)
输出结果:
Name Age City
1 Bob 30 London
- 使用 .loc[] 进行布尔索引: 可以使用 .loc[] 方法结合布尔索引来同时选择特定行和列
# 使用 .loc[] 进行布尔索引
selected_data = df.loc[df['Age'] > 30, ['Name', 'City']]
print(selected_data)
输出结果:
Name City
2 Charlie Paris
3 David Tokyo
4 Eva Sydney
# 选择 Name 长度大于等于6的行
selected_rows = df.loc[df['Name'].str.len() >= 6]
print(selected_rows)
输出结果:
Name City
0 Alice New York
2 Charlie Paris
缺失数据的处理
检测缺失数据:
使用 isnull()
方法检测 DataFrame 中的缺失值。该方法返回一个布尔值 DataFrame,其中每个元素表示对应位置是否为缺失值。
import pandas as pd
import numpy as np
data = {'Name': ['Alice', 'Bob', np.nan],
'Age': [25, np.nan, 35],
'City': ['New York', 'London', np.nan]}
df = pd.DataFrame(data)
# 检测 DataFrame 中的缺失值
missing_values = df.isnull()
print(missing_values)
输出结果:
Name Age City
0 False False False
1 False True False
2 True False True
删除包含缺失数据的行或列:
使用 dropna()
方法删除包含任何(默认情况下)或所有(通过设置参数 how='all'
)缺失值的行。
使用 dropna(axis=1
) 方法删除包含任何(默认情况下)或所有(通过设置参数 how='all'
)缺失值的列。
# 删除包含缺失值的行
df_clean_rows = df.dropna()
print(df_clean_rows)
输出结果:
Name Age City
0 Alice 25.0 New York
# 删除包含缺失值的列
df_clean_cols = df.dropna(axis=1)
print(df_clean_cols)
输出结果:
Empty DataFrame
Columns: []
Index: [0, 1, 2]
填充缺失数据:
使用 fillna(value) 方法将 DataFrame 中的缺失值替换为指定的数值或方法。
使用常数填充:fillna(0) 将所有缺失值替换为零。
使用平均数填充:fillna(df.mean()) 将每列中的缺失值替换为该列的平均数。
# 使用常数填充缺失值
df_filled_constant = df.fillna(0)
print(df_filled_constant)
输出结果:
Name Age City
0 Alice 25.0 New York
1 Bob 0.0 London
2 0 35.00
import pandas as pd
data = {'Name': ['Alice', 'Bob', None],
'Age': [25, None, 35],
'City': ['New York', 'London', None]}
df = pd.DataFrame(data)
# 使用前一行数据填充缺失值
df_filled_previous = df.fillna(method='ffill')
print(df_filled_previous)
输出结果:
Name Age City
0 Alice 25.0 New York
1 Bob 25.0 London
2 Bob 35.00 London
set(df.tolist)
set(df[].tolist()) 是一种将 DataFrame 列中的唯一值提取为集合的方法。它可以用于获取列中的不同值,而不包括重复的值。
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
'Age': [25, 30, 35, 40, 45],
'City': ['New York', 'London', 'Paris', 'Tokyo' ,'Sydney']}
df = pd.DataFrame(data)
# 提取 Name 列中的唯一值
unique_names = set(df['Name'].tolist())
print(unique_names)
输出结果:
{'Charlie', 'David', 'Bob', 'Alice','Eva'}
在上述示例中,我们使用 df['Name'].tolist() 将 DataFrame df 中 Name 列的值转换为列表,并使用 set() 函数将其转换为集合。最后,我们打印了包含唯一名字的集合。
df.join()
import pandas as pd
data1 = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35]}
df1 = pd.DataFrame(data1)
data2 = {'City': ['New York', 'London', 'Paris'],
'Salary': [5000, 6000, 7000]}
df2 = pd.DataFrame(data2)
# 使用索引连接两个 DataFrame
joined_df = df1.join(df2)
print(joined_df)
输出结果:
Name Age City Salary
0 Alice 25.0 New York 5000
1 Bob 30.0 London 6000
2 Charlie 35.0 Paris 7000
分组操作
- 使用 groupby() 方法根据指定的列或多个列对数据进行分组。这将返回一个 GroupBy 对象,可以在其上应用聚合函数
- 可以使用单个列名作为参数,也可以使用多个列名的列表作为参数
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
'City': ['New York', 'London', 'Paris', 'London' ,'Paris'],
'Age': [25, 30, 35, 40, 45],
'Salary': [5000, 6000, 7000, 5500 ,7500]}
df = pd.DataFrame(data)
# 按照 City 列进行分组
grouped_data = df.groupby('City')
print(df)
print('--------------------------------')
# 打印每个分组的内容
for city, group in grouped_data:
print(f"City: {city}")
print(group)
print("\n")
复合索引
单个列索引:
在 Pandas 中,可以使用 set_index() 方法将某一列设置为索引。
这将返回一个新的 DataFrame,并将指定的列作为索引。
索引可以是数值、字符串或其他类型。
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'London', 'Paris']}
df = pd.DataFrame(data)
# 将 Name 列设置为索引
df_with_index = df.set_index('Name')
print(df_with_index)
输出结果:
Age City
Name
Alice 25.0 New York
Bob 30.0 London
Charlie 35.0 Paris
复合索引:
复合索引是由多个列组成的层次化结构。它提供了更灵活和精细的数据访问方式。
可以通过传递多个列名给 set_index() 方法来创建复合索引。
# 将 Name 和 City 列设置为复合索引
df_with_multi_index = df.set_index(['Name', 'City'])
print(df_with_multi_index)
输出结果:
Age
Name City
Alice New York 25.0
Bob London 30.0
Charlie Paris 35.0
在上述示例中,我们使用 set_index() 方法将 DataFrame df 的 Name 和 City 列设置为复合索引,并打印了带有复合索引的 DataFrame。
可以使用 .loc[] 或 .iloc[] 访问具有复合索引的 DataFrame 中的数据。例如:
# 使用 .loc[] 访问具有复合索引的 DataFrame 中的数据
print(df_with_multi_index.loc[('Alice', 'New York')])
输出结果:
Age 25.0
Name: (Alice, New York), dtype: float64
.index.unique()
方法来获取索引的唯一值
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'London', 'Paris']}
df = pd.DataFrame(data)
# 获取索引的唯一值
unique_index_values = df.index.unique()
print(unique_index_values)
输出结果:
Index([0, 1, 2], dtype='object')
.swaplevel()
.swaplevel() 方法用于交换 DataFrame 或 MultiIndex 的层级
- 交换两个层级的顺序:df.swaplevel(level1, level2, axis)
- 仅对索引进行操作:index.swaplevel(level1, level2)
时间序列
pd.date_range()
:
- start: 范围的起始日期,可以是字符串、datetime对象或Timestamp对象。
- end: 范围的结束日期,可以是字符串、datetime对象或Timestamp对象。
- periods: 生成的日期数量,默认为None。如果指定了periods参数,则会根据指定的数量平均间隔生成日期范围。
- freq:
日期频率字符串或DateOffset对象,表示每个时间点之间的间隔,默认为’D’(天)。其他常见频率包括’H’(小时)、‘M’(分钟)、‘S’(秒)等。也可以使用自定义频率字符串,如’BQS-JAN’表示每季度开始月份为1月份的工作日频率。
import pandas as pd
df = pd.date_range(start='20220912', end='20230912')
print(df)
DatetimeIndex(['2022-09-12', '2022-09-13', '2022-09-14', '2022-09-15',
'2022-09-16', '2022-09-17', '2022-09-18', '2022-09-19',
'2022-09-20', '2022-09-21',
...
'2023-09-03', '2023-09-04', '2023-09-05', '2023-09-06',
'2023-09-07', '2023-09-08', '2023-09-09', '2023-09-10',
'2023-09-11', '2023-09-12'],
dtype='datetime64[ns]', length=366, freq='D')
import pandas as pd
df = pd.date_range(start='20220912', end='20230912',freq='BM')
print(df)
DatetimeIndex(['2022-09-30', '2022-10-31', '2022-11-30', '2022-12-30',
'2023-01-31', '2023-02-28', '2023-03-31', '2023-04-28',
'2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31'],
dtype='datetime64[ns]', freq='BM')
import pandas as pd
df = pd.date_range(start='20220912', periods=10,freq='BM')
print(df)
DatetimeIndex(['2022-09-30', '2022-10-31', '2022-11-30', '2022-12-30',
'2023-01-31', '2023-02-28', '2023-03-31', '2023-04-28',
'2023-05-31', '2023-06-30'],
dtype='datetime64[ns]', freq='BM')
pd.to_datetime
:
import pandas as pd
# 假设有一个DataFrame df,包含"timeStamp"列
df = pd.DataFrame({'timeStamp': ['2021-01-01', '2021-02-01', '2021-03-01'],
'value': [10, 20, 30]})
# 将"timeStamp"列转换为时间戳格式
df['timeStamp'] = pd.to_datetime(df['timeStamp'], format='%Y-%m-%d')
print(df)
输出结果:
timeStamp value
0 2021-01-01 10
1 2021-02-01 20
2 2021-03-01 30
通过指定format='%Y-%m-%d'参数来告诉pd.to_datetime()函数输入字符串的日期格式。
这样就可以确保正确地解析日期,并将其转换为pandas中的DateTime对象。
pd.DatetimeIndex
:
时间索引:可以使用pd.DatetimeIndex对象将日期作为索引来创建Series或DataFram
重采样
重采样是指将时间序列从一个频率转换为另一个频率的过程。重采样可以实现降采样(将高频率数据转换为低频率数据)和升采样(将低频率数据转换为高频率数据)
pandas提供了resample()
函数来执行重采样操作。该函数的常用参数包括:
- rule: 用于指定目标频率的字符串或DateOffset对象。例如,'D’表示每天,'H’表示每小时,'M’表示每月等。
- how: 用于指定聚合操作的方法。常见的方法包括’mean’(均值)、‘sum’(总和)、‘min’(最小值)、‘max’(最大值)等。
- closed:
用于控制区间闭合方式,默认为左闭右闭(‘left’)。还可以选择左开右闭(‘right’)、左闭右开(‘both’)或者左开右开(‘neither’)。 - label: 用于控制结果索引标签,默认为取区间内第一个时间点作为索引标签。
import pandas as pd
# 创建一个包含10个连续天数的时间序列
dates = pd.date_range(start='2021-01-01', periods=10, freq='D')
data = pd.Series(range(len(dates)), index=dates)
# 将每日数据聚合为每月平均值
monthly_avg = data.resample('M').mean()
print(monthly_avg)
# Output:
# 2021-01-31 15.0
# Freq: M, dtype: float64
# 将每日数据聚合为每周总和
weekly_sum = data.resample('W').sum()
print(weekly_sum)
# Output:
# 2021-01-03 3
# 2021-01-10 28
# Freq: W-SUN, dtype: int64
# 将每月平均值升采样为每天,使用前向填充缺失值
daily_data = monthly_avg.resample('D').ffill()
print(daily_data)