1 数据结构
1.1 Series
创建和初始化
pandas
中的Series
是一种一维数组的数据结构,可以包含不同数据类型的元素。
以下是Series
的创建和初始化的方法:
import pandas as pd
# 通过列表创建Series
data_list = [1, 2, 3, 4]
series_from_list = pd.Series(data_list)
print(series_from_list)
0 1
1 2
2 3
3 4
dtype: int64
上面的例子,在创建Series
时pandas
自动创建了索引。 我们也可以自己指定标签索引:
# 指定标签索引
data_list = [1, 2, 3, 4]
index_list = ['a', 'b', 'c', 'd']
# data表示数据,index表示索引
series_from_list_name = pd.Series(data=data_list, index=index_list)
print(series_from_list)
0 1
1 2
2 3
3 4
dtype: int64
# 通过NumPy数组创建Series
import numpy as np
data_array = np.array([10, 20, 30, 40])
series_from_array = pd.Series(data_array)
print(series_from_array)
0 10
1 20
2 30
3 40
dtype: int32
# 通过字典创建Series
# 该方法字典中的键就是标签索引,值就是数据
data_dict = {'a': 100, 'b': 200, 'c': 300}
series_from_dict = pd.Series(data_dict)
print(series_from_dict)
a 100
b 200
c 300
dtype: int64
索引操作
Series的元素可以通过索引进行访问。索引可以是默认的整数索引,也可以是自定义的标签索引。
# 默认整数索引
print("Element at index 2:", series_from_dict[1]) # Element at index 2: 200
# 自定义标签索引
print("\nElement with label 'b':", series_from_dict['b']) # Element with label 'b': 200
数学运算
Series支持多种数学运算,包括加法、减法、乘法和除法。
# 加法
result_addition = series_from_list + series_from_array
print("Addition result:")
print(result_addition)
# 乘法
result_multiplication = series_from_list * 2
print("\nMultiplication result:")
print(result_multiplication)
Addition result:
0 11
1 22
2 33
3 44
dtype: int64
Multiplication result:
0 2
1 4
2 6
3 8
dtype: int64
对齐操作
在进行数学运算时,Series会自动对齐具有相同标签的元素。
# 对齐操作
data1 = {'a': 10, 'b': 20, 'c': 30}
data2 = {'b': 5, 'c': 15, 'd': 25}
series1 = pd.Series(data1)
series2 = pd.Series(data2)
result_alignment = series1 + series2
print("Result after alignment:")
print(result_alignment)
Result after alignment:
a NaN
b 25.0
c 45.0
d NaN
dtype: float64
result_alignment
将只包含两个Series
中共有的标签,对应位置的元素相加。
1.2 DataFrame
创建和初始化
DataFrame
是pandas
中最常用的数据结构之一,它是一个二维标记的数据结构,类似于电子表格或SQL表。下面是一些DataFrame
的创建和初始化的方法:
# 通过字典创建DataFrame
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'San Francisco', 'Los Angeles']}
df_from_dict = pd.DataFrame(data)
print("DataFrame from dictionary:")
print(df_from_dict)
# 通过列表创建DataFrame
data_list_of_lists = [['Alice', 25, 'New York'],
['Bob', 30, 'San Francisco'],
['Charlie', 35, 'Los Angeles']]
columns = ['Name', 'Age', 'City']
df_from_list = pd.DataFrame(data_list_of_lists, columns=columns)
print("\nDataFrame from list of lists:")
print(df_from_list)
DataFrame from dictionary:
Name Age City
0 Alice 25 New York
1 Bob 30 San Francisco
2 Charlie 35 Los Angeles
DataFrame from list of lists:
Name Age City
0 Alice 25 New York
1 Bob 30 San Francisco
2 Charlie 35 Los Angeles
列操作
DataFrame
的列可以通过列名进行访问和操作
# 访问列
names_column = df_from_dict['Name']
print("Names column:")
print(names_column)
# 添加新列
df_from_dict['Country'] = ['USA', 'USA', 'USA']
print("\nDataFrame after adding 'Country' column:")
print(df_from_dict)
Names column:
0 Alice
1 Bob
2 Charlie
Name: Name, dtype: object
DataFrame after adding 'Country' column:
Name Age City Country
0 Alice 25 New York USA
1 Bob 30 San Francisco USA
2 Charlie 35 Los Angeles USA
行操作
DataFrame
的行可以通过行索引进行访问和操作
# 通过行索引访问行
row_1 = df_from_dict.loc[0]
print("Row at index 0:")
print(row_1)
# 添加新行
new_row = {'Name': 'David', 'Age': 28, 'City': 'Chicago', 'Country': 'USA'}
df_from_dict = df_from_dict.append(new_row, ignore_index=True) # 新行会被添加到末尾,并使用默认的整数索引进行编号
print("\nDataFrame after adding new row:")
print(df_from_dict)
Row at index 0:
Name Alice
Age 25
City New York
Country USA
Name: 0, dtype: object
DataFrame after adding new row:
Name Age City Country
0 Alice 25 New York USA
1 Bob 30 San Francisco USA
2 Charlie 35 Los Angeles USA
3 David 28 Chicago USA
在最新的版本中,会提示我们append()
函数在未来可能会弃用,我再向大家介绍一下concat()
函数。
concat()
函数是pandas中用于合并(连接)多个Series或DataFrame的函数。它允许按照指定的轴(默认是行轴)将多个对象进行连接,可以水平连接(按列连接)或垂直连接(按行连接)。下面是concat()
abs函数的基本用法和参数说明:
pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True)
objs
: 需要合并的Series或DataFrame对象,可以是一个列表或字典。axis
: 指定合并的方向,0表示按行连接(垂直连接),1表示按列连接(水平连接)。默认为0。join
: 指定连接方式,'outer’表示并集(对所有索引进行并集),‘inner’表示交集(只对索引的交集进行连接)。默认为’outer’。ignore_index
: 是否忽略原始对象的索引,如果为True,则生成新的整数索引。默认为False。keys
: 用于创建层次化索引的标签数组或标签列表。如果传递了多个对象(如字典或DataFrame的列表),则需要使用keys参数来创建层次化索引。默认为None。levels
: 指定用于层次化索引的唯一值,可以是数组、列表或元组。names
: 指定层次化索引的名称。verify_integrity
: 检查合并后的对象是否有重复索引。如果设置为True,并且有重复索引,则会引发异常。默认为False。sort
: 是否按照字典顺序对结果进行排序。默认为False。copy
: 是否对源对象进行复制。默认为True。
import pandas as pd
# 创建两个DataFrame对象
df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
df2 = pd.DataFrame({'A': [7, 8, 9], 'B': [10, 11, 12]})
# 垂直连接(按行连接)
result_vertical = pd.concat([df1, df2])
print("垂直连接:")
print(result_vertical)
# 水平连接(按列连接)
result_horizontal = pd.concat([df1, df2], axis=1)
print("\n水平连接:")
print(result_horizontal)
垂直连接:
A B
0 1 4
1 2 5
2 3 6
0 7 10
1 8 11
2 9 12
水平连接:
A B A B
0 1 4 7 10
1 2 5 8 11
2 3 6 9 12
数据对齐
与Series
类似,DataFrame
在进行操作时会自动对齐具有相同标签的元素。
# 创建两个DataFrame进行对齐操作
data1 = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35]}
data2 = {'Name': ['David', 'Eve', 'Frank'],
'Age': [28, 22, 40]}
df1 = pd.DataFrame(data1, index=['a', 'b', 'c'])
df2 = pd.DataFrame(data2, index=['b', 'c', 'd'])
# 对齐操作
result_alignment = df1 + df2
print("\nResult after alignment:")
print(result_alignment)
Result after alignment:
Name Age
a NaN NaN
b BobDavid 58.0
c CharlieEve 57.0
d NaN NaN
2 数据操作
2.1 索引和选择
在pandas
中,对数据进行索引和选择是非常常见的操作。可以通过标签或位置来选择数据。
使用标签
通过标签进行索引和选择是一种常见的方法,可以使用loc[]方法。
# 创建一个示例DataFrame
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'San Francisco', 'Los Angeles']}
df = pd.DataFrame(data)
# 使用标签选择行和列
selected_data = df.loc[0, 'Name']
print("Selected data using label:")
print(selected_data)
Selected data using label:
Alice
在上面的示例中,df.loc[0, 'Name']
选择了第一行的Name列数据。
使用位置
除了使用标签外,还可以使用位置来进行索引和选择,使用iloc[]
方法。
这里要注意的一点是,loc[]
中可以混合使用位置索引和标签索引,但是iloc[]
中只能使用位置索引。
# 使用位置选择行和列
selected_data = df.iloc[0, 1]
print("\nSelected data using position:")
print(selected_data)
Selected data using position:
25
这里的df.iloc[0, 1]
选择了第一行第二列的数据,因为iloc[]
使用的是位置而不是标签。
布尔索引
布尔索引是一种非常强大的工具,可以根据条件选择数据。
# 使用布尔索引选择满足条件的行
selected_data = df[df['Age'] > 30]
print("\nSelected data using boolean indexing:")
print(selected_data)
Selected data using boolean indexing:
Name Age City
2 Charlie 35 Los Angeles
重置索引
有时候当我们执行了一些对DataFrame的操作后,DataFrame的索引可能会被打乱,这会影响后面的一些操作,我们通常需要重新设置索引,可以用到reset_index()
函数。
df = df.reset_index()
df.reset_index(drop=True, inplace=True)
df = df.reset_index()
:这是最原始的方法,这样操作后会生成一个新的index
列存储原有的索引,并且注意一定要重新赋值给df
,不然就只是执行了操作,df
没有改变。df.reset_index(drop=True, inplace=True)
:我通常使用这种方法,比较简便drop=True
表示不保存原有的索引inplace=True
表示在原地执行操作,我们就不需要再次赋值给df
。
2.2 切片和过滤
切片和过滤是处理数据的常见操作,可以帮助我们根据特定的条件筛选出感兴趣的数据子集。在pandas
中,可以使用切片和布尔索引来实现这些操作。
切片也可以使用loc[]
方法和iloc[]
方法,只需要在切分行和列的时候遵守列表的切片规则就可以了。
行切片
可以使用切片操作选择DataFrame的行。
# 使用行切片选择一定范围的行
sliced_data = df[1:3]
print("Sliced data using row slicing:")
print(sliced_data)
Sliced data using row slicing:
Name Age City
1 Bob 30 San Francisco
2 Charlie 35 Los Angeles
这里的df[1:3]
选择了索引为1到2的行(不包括索引为3的行)。
列切片
同样,可以使用切片操作选择DataFrame的列。
# 使用列切片选择一定范围的列
sliced_data = df.loc[:, 'Name':'Age']
print("\nSliced data using column slicing:")
print(sliced_data)
Sliced data using column slicing:
Name Age
0 Alice 25
1 Bob 30
2 Charlie 35
这里的df.loc[:, 'Name':'Age']
选择了Name
到Age
之间的列。
条件过滤
可以根据特定条件来过滤DataFrame的,该操作其实和布尔索引是同样的原理行。
# 使用条件过滤选择满足条件的行
filtered_data = df[df['Age'] > 30]
print("\nFiltered data using condition:")
print(filtered_data)
Filtered data using condition:
Name Age City
2 Charlie 35 Los Angeles
2.3 赋值和修改
在处理数据时,有时需要对数据进行修改或赋值操作。pandas提供了简单而灵活的方法来实现这些操作。
单值赋值
可以通过索引或切片来对DataFrame中的单个值进行赋值。
# 创建一个示例DataFrame
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'San Francisco', 'Los Angeles']}
df = pd.DataFrame(data)
# 单值赋值
df.loc[0, 'Age'] = 26
print("DataFrame after single value assignment:")
print(df)
DataFrame after single value assignment:
Name Age City
0 Alice 26 New York
1 Bob 30 San Francisco
2 Charlie 35 Los Angeles
在上面的示例中,我们将第一行的Age
值修改为26。
批量赋值
也可以通过条件或切片来对DataFrame中的多个值进行批量赋值。
# 批量赋值
df.loc[df['Age'] > 30, 'City'] = 'Unknown'
print("\nDataFrame after bulk assignment:")
print(df)
DataFrame after bulk assignment:
Name Age City
0 Alice 26 New York
1 Bob 30 San Francisco
2 Charlie 35 Unknown
这里的df.loc[df['Age'] > 30, 'City'] = 'Unknown'
将年龄大于30的行的City
列值都修改为Unknown
。
函数修改
还可以使用函数来修改DataFrame中的现有数据:
# 使用函数修改数据
df['Age'] = df['Age'].apply(lambda x: x + 1)
print("\nDataFrame after applying function:")
print(df)
DataFrame after applying function:
Name Age City
0 Alice 27 New York
1 Bob 31 San Francisco
2 Charlie 36 Unknown
apply()函数
上面提到,我们可以使用函数来修改DataFrame的值,这里我们重点讲解一下apply()
函数。
apply()
函数是pandas中非常强大和灵活的函数之一,它能够对DataFrame或Series中的每个元素应用自定义函数,从而实现对数据的批量处理。下面详细讲解一下apply()
函数的使用。
apply()
函数的基本语法:
DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwds)
func
: 自定义函数,可以是函数名或lambda函数。axis
: 指定对行还是列进行操作,axis=0表示对列操作(默认值),axis=1表示对行操作。raw
: 是否直接传递原始数据给函数,默认为False,表示传递的是数据的索引标签。如果为True,则传递的是数据的原始值。result_type
: 指定返回结果的数据类型,可选值为None、‘expand’、‘reduce’,默认为None。args
: 传递给函数的额外参数,以元组形式传递。
示例:假设我们有一个包含员工工资信息的DataFrame,其中包括员工姓名、工资和工龄。现在我们想要对工资进行调整,比如增加一定的津贴,我们可以使用apply()
函数来实现。
import pandas as pd
# 创建示例DataFrame
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Salary': [50000, 60000, 70000],
'Years': [5, 7, 10]}
df = pd.DataFrame(data)
# 定义一个函数,增加津贴
def adjust_salary(salary, allowance):
return salary + allowance
# 使用apply()函数对Salary列进行操作,增加津贴
allowance = 5000
df['Salary'] = df['Salary'].apply(adjust_salary, args=(allowance,))
print(df)
Name Salary Years
0 Alice 55000 5
1 Bob 65000 7
2 Charlie 75000 10
在这个示例中,我们首先定义了一个adjust_salary()
函数,用于将工资和津贴相加。然后,我们使用apply()
函数将这个函数应用到Salary
列上,实现了对工资的调整。最终输出了调整后的DataFrame。
replace()函数
df['type'] = df['type'].replace({'a': 1, 'b': 2, 'c': 3})
这将把 df
的type
列中的a
替换为 1,b
替换为 2,c
替换为 3。
2.4 排序
排序是数据分析中常用的操作之一,可以帮助我们按照特定的规则重新排列数据。在pandas中,可以使用sort_index()
和sort_values()
函数来实现排序操作。
按索引排序
使用sort_index()
函数可以按照索引对DataFrame进行排序,这会将DataFrame按照索引进行升序排序。。
# 按索引排序
df_sorted_index = df.sort_index()
print("DataFrame sorted by index:")
print(df_sorted_index)
DataFrame sorted by index:
Name Salary Years
0 Alice 55000 5
1 Bob 65000 7
2 Charlie 75000 10
按值排序
使用sort_values()
函数可以按照列的值对DataFrame进行排序。
# 按值排序
df_sorted_values = df.sort_values(by='Salary', ascending=False)
print("\nDataFrame sorted by values (descending order of Salary):")
print(df_sorted_values)
DataFrame sorted by values (descending order of Salary):
Name Salary Years
2 Charlie 75000 10
1 Bob 65000 7
0 Alice 55000 5
这里的by='Salary'
表示按照Salary
列的值进行排序,ascending=False
表示降序排序,如果为True
的话就是升序排列,默认为升序。
多级排序
理解多级排序需要首先理解多级索引。在pandas中,多级索引是指DataFrame中具有多个层级的索引,类似于Excel中的多级行标签。多级索引的情况下,我们可以按照不同的级别进行排序。
让我们以一个简单的示例来说明多级排序的概念和实现:。
import pandas as pd
# 创建一个示例的多级索引Series
index = pd.MultiIndex.from_tuples([('A', 1), ('A', 2), ('B', 1), ('B', 2)])
data = pd.Series([100, 200, 300, 400], index=index)
# 将多级索引Series转换成DataFrame
df_multi_index = data.unstack()
print(df_multi_index)
1 2
A 100 200
B 300 400
-
pd.MultiIndex.from_tuples()
: 这个函数是用来创建多级索引的,它接受一个元组列表作为输入,并返回一个多级索引对象。元组列表中的每个元组代表了一个索引的标签,每个元组的元素对应一个层级的索引标签。例如,[('A', 1), ('A', 2), ('B', 1), ('B', 2)]
表示了一个具有两个层级的索引,第一个层级的标签为'A'
和'B'
,第二个层级的标签为1
和2
。 -
data.unstack()
: 这个方法是将多级索引的Series转换成DataFrame。在我们的示例中,data
是一个具有多级索引的Series对象。unstack()
方法将多级索引的Series对象转换成DataFrame,其中第一级索引变成了列索引,而第二级索引变成了行索引。换句话说,它将多级索引中的其中一层级(一般是最内层)提取出来作为新的列,形成一个二维的DataFrame。
接下来,让我们对这个多级索引DataFrame进行排序:
# 多级索引排序,第一级升序,第二级降序
df_multi_index_sorted = df_multi_index.sort_index(level=0, ascending=True)
df_multi_index_sorted = df_multi_index.sort_index(level=1, ascending=False)
print(df_multi_index_sorted)
1 2
B 300 400
A 100 200
在这里,sort_index()
函数用于对索引进行排序,level
指定了按照第一级和第二级索引进行排序。ascending
指定按照升序还是降序排序,True
表示升序,False
表示降序。
3 数据清洗
数据清洗是数据分析过程中非常重要的一步,它涉及到处理缺失数据、处理重复值以及数据类型转换等操作。在这一部分,我们将详细介绍如何进行数据清洗。
3.1 处理缺失数据
缺失数据在实际数据中经常会出现,可能是由于采集过程中的错误、数据录入问题或者其他原因造成的。在pandas中,我们可以使用一些方法来处理缺失数据:
查找缺失数据
我们可以使用isnull()
函数来检查DataFrame中是否存在缺失数据。
import pandas as pd
# 创建示例数据集
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Emily'],
'Age': [20, 25, None, 22, 30],
'Grade': [85, 90, 75, None, 95],
'Birthdate': ['1998-05-15', '1996-02-28', '2000-11-10', '1999-08-20', None]}
df = pd.DataFrame(data)
# 查找缺失数据
missing_data = df.isnull()
print("缺失数据情况:")
print(missing_data)
缺失数据情况:
Name Age Grade Birthdate
0 False False False False
1 False False False False
2 False True False False
3 False False True False
4 False False False True
isnull()
函数不接受任何参数,它只是用于查找DataFrame中的缺失数据,并返回一个布尔类型的DataFrame,其中缺失值为True
,非缺失值为False
。
删除缺失数据
使用dropna()
函数删除含有缺失数据的行或列
# 删除含有缺失数据的行
df_without_missing = df.dropna(axis=0)
# 删除含有缺失数据的列
df_without_missing_col = df.dropna(axis=1)
除了使用axis
指定删除行还是列,我们更常见的是使用subset
参数在指定的列范围内搜索缺失值,然后删除有缺失值的行。
# 删除含有缺失数据的行,仅考虑Age列和Grade列
df_without_missing_rows = df.dropna(subset=['Age', 'Grade'])
填充缺失数据
使用fillna()
函数用指定的值填充缺失数据,可以使用常数值,也可以使用均值、中位数等统计量。
# 填充缺失数据,用0填充
df_filled = df.fillna(0)
# 填充缺失数据,用均值填充
df_filled_mean = df.fillna(df.mean())
甚至还可以指定某些具体的列使用具体的值
df_filled = df.fillna({'Age': df['Age'].mean(), 'Grade': df['Grade'].median(), 'Birthdate': '1990-01-01'})
3.2 处理重复值
重复值可能会对数据分析产生误导,因此我们需要对其进行处理。
查找重复值
我们可以使用duplicated()
函数来检查DataFrame中是否存在重复值。
# 检查重复值
duplicate_rows = df.duplicated()
删除重复值
使用drop_duplicates()
函数来删除DataFrame中的重复值。
# 删除重复值
df_unique = df.drop_duplicates()
3.3 数据类型转换
在数据清洗过程中,有时候需要对数据的类型进行转换,例如将字符串类型转换为数字类型,或者处理日期和时间数据类型。
转换整数、浮点数、字符串等
# 将字符串类型转换为整数类型
df['Age'] = df['Age'].astype(int)
处理日期和时间数据类型
# 处理日期和时间数据类型
df['Date'] = pd.to_datetime(df['Date'])
数据清洗综合案例讲解:假设我们有一个包含学生姓名、年龄、成绩和出生日期的数据集。我们将演示如何处理缺失数据、重复值和数据类型转换。
import pandas as pd
# 创建示例数据集
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Emily'],
'Age': [20, 25, None, 22, 30],
'Grade': [85, 90, 75, None, 95],
'Birthdate': ['1998-05-15', '1996-02-28', '2000-11-10', '1999-08-20', None]}
df = pd.DataFrame(data)
# 显示原始数据集
print("原始数据集:")
print(df)
# 1. 发现缺失数据
missing_data = df.isnull()
print("\n缺失数据情况:")
print(missing_data)
# 2. 删除含有缺失数据的行
df_without_missing = df.dropna()
print("\n删除缺失数据后的数据集:")
print(df_without_missing)
# 3. 填充缺失数据
df_filled = df.fillna({'Age': df['Age'].mean(), 'Grade': df['Grade'].median(), 'Birthdate': '1990-01-01'})
print("\n填充缺失数据后的数据集:")
print(df_filled)
# 4. 发现重复值
duplicate_rows = df.duplicated()
print("\n重复值情况:")
print(duplicate_rows)
# 5. 删除重复值
df_unique = df.drop_duplicates()
print("\n删除重复值后的数据集:")
print(df_unique)
# 6. 数据类型转换
df_filled['Birthdate'] = pd.to_datetime(df_filled['Birthdate'])
print("\n数据类型转换后的数据集:")
print(df_filled)
原始数据集:
Name Age Grade Birthdate
0 Alice 20.0 85.0 1998-05-15
1 Bob 25.0 90.0 1996-02-28
2 Charlie NaN 75.0 2000-11-10
3 David 22.0 NaN 1999-08-20
4 Emily 30.0 95.0 None
缺失数据情况:
Name Age Grade Birthdate
0 False False False False
1 False False False False
2 False True False False
3 False False True False
4 False False False True
删除缺失数据后的数据集:
Name Age Grade Birthdate
0 Alice 20.0 85.0 1998-05-15
1 Bob 25.0 90.0 1996-02-28
填充缺失数据后的数据集:
Name Age Grade Birthdate
0 Alice 20.00 85.0 1998-05-15
1 Bob 25.00 90.0 1996-02-28
2 Charlie 24.25 75.0 2000-11-10
3 David 22.00 87.5 1999-08-20
4 Emily 30.00 95.0 1990-01-01
重复值情况:
0 False
1 False
2 False
3 False
4 False
dtype: bool
删除重复值后的数据集:
Name Age Grade Birthdate
0 Alice 20.0 85.0 1998-05-15
1 Bob 25.0 90.0 1996-02-28
2 Charlie NaN 75.0 2000-11-10
3 David 22.0 NaN 1999-08-20
4 Emily 30.0 95.0 None
数据类型转换后的数据集:
Name Age Grade Birthdate
0 Alice 20.00 85.0 1998-05-15
1 Bob 25.00 90.0 1996-02-28
2 Charlie 24.25 75.0 2000-11-10
3 David 22.00 87.5 1999-08-20
4 Emily 30.00 95.0 1990-01-01
4 数据统计和计算
4.1 描述性统计
描述性统计是对数据集的基本统计量进行计算,包括平均值、中位数、标准差、最大值和最小值
# 平均数
mean_grade = df['Grade'].mean()
print("平均成绩:", mean_grade)
# 众数
mode_age = df['Age'].mode()
print("年龄众数:", mode_age)
# 中位数
median_age = df['Age'].median()
print("中位数年龄:", median_age)
# 标准差
std_deviation_grade = df['Grade'].std()
print("成绩标准差:", std_deviation_grade)
# 方差
variance_age = df['Age'].var()
print("年龄方差:", variance_age)
# 最大值
max_grade = df['Grade'].max()
print("最高成绩:", max_grade)
# 最小值
min_grade = df['Grade'].min()
print("最低成绩:", min_grade)
# 四分位数
quartiles_age = df['Age'].quantile([0.25, 0.5, 0.75])
print("年龄四分位数:")
print(quartiles_age)
4.2 聚合和分组
聚合操作是对数据集中的数据进行汇总计算,通常与分组操作一起使用。我们可以使用groupby()
函数按照指定的列进行分组,然后对每个组应用.agg()
聚合函数。
# 创建示例数据集
data = {'Name': ['Alice', 'Bob', 'Alice', 'Bob', 'Alice'],
'Age': [20, 25, 22, 22, 30],
'Grade': [85, 90, 75, 84, 95],
'Birthdate': ['1998-05-15', '1996-02-28', '2000-11-10', '1999-08-20', '2000-11-10']}
df = pd.DataFrame(data)
# 按照姓名进行分组,并计算每个组的平均年龄和平均成绩
grouped_data = df.groupby('Name').agg({'Age': 'mean', 'Grade': 'median'})
print("按照姓名分组后的聚合结果:")
print(grouped_data)
按照姓名分组后的聚合结果:
Age Grade
Name
Alice 24.0 85.0
Bob 23.5 87.0
4.3 窗口函数
窗口函数是一种在移动窗口上进行计算的方法,例如计算移动平均值、累计和等操作。在pandas中,可以使用rolling()
函数来实现窗口函数的计算。
# 使用rolling函数计算移动平均值
rolling_mean = df['Grade'].rolling(window=2).mean()
print("移动平均值:")
print(rolling_mean)
移动平均值:
0 NaN
1 87.5
2 82.5
3 79.5
4 89.5
Name: Grade, dtype: float64
这里的window=2
表示窗口大小为2,即每两个数据进行一次计算。
5 数据输入和输出
在实际数据分析过程中,我们通常需要从外部数据源读取数据,或将处理后的数据保存到外部文件中。pandas提供了丰富的功能来实现数据的输入和输出。
5.1 读取数据
pandas支持从多种文件格式中读取数据,包括CSV、Excel、SQL等。
# 从CSV文件读取数据
df_csv = pd.read_csv('data.csv')
# 从Excel文件读取数据
df_excel = pd.read_excel('data.xlsx')
# 从SQL数据库读取数据
import sqlite3
conn = sqlite3.connect('database.db')
query = "SELECT * FROM table_name"
df_sql = pd.read_sql(query, conn)
conn.close()
另外,我们还可以设置参数:
header
参数用于指定标题行的位置,默认为'infer'
,表示自动识别。index_col
参数用于指定索引列的位置,默认为None
,表示不使用任何列作为索引。
# 从CSV文件读取数据,将第一行作为标题行,将第一列作为索引列
df_csv = pd.read_csv('data.csv', header=0, index_col=0)
5.2 写入数据
除了读取数据,pandas也支持将处理后的数据保存到不同格式的文件中。
# 将数据保存到CSV文件
df.to_csv('output.csv', index=False)
# 将数据保存到Excel文件
df.to_excel('output.xlsx', index=False)
# 将数据保存到SQL数据库
conn = sqlite3.connect('new_database.db')
df.to_sql('new_table', conn, index=False, if_exists='replace')
conn.close()
header
参数用于指定是否将列名写入文件,默认为True
。index
参数用于指定是否将索引列写入文件,默认为True
。
# 将数据保存到CSV文件,包含标题行和索引列
df.to_csv('output.csv', header=True, index=True)
6 时间序列数据
时间序列数据是一种按照时间顺序排列的数据,通常是固定时间间隔内收集的数据。在pandas中,有许多功能可以处理时间序列数据,包括日期和时间处理、重采样和频率转换以及移动窗口统计等。
6.1 日期和时间处理
pandas提供了强大的日期和时间处理功能,可以解析、操作和格式化日期和时间数据。
pd.date_range()
函数参数解释:
start
: 表示日期范围的起始日期或时间戳。end
: 表示日期范围的结束日期或时间戳。periods
: 表示要生成的日期数量,这决定了日期范围的长度。freq
: 表示日期范围的频率。这可以是一个字符串,也可以是pandas中的DateOffset
对象。常用的频率包括:- D:天
- W:周
- M:月
- Q:季度
- A:年
- 也可以通过
+
号和数字来表示间隔,例如'5D'
表示每隔5天。
# 创建一个日期范围
dates = pd.date_range('2024-01-01', periods=5, freq='D')
# 创建一个包含日期和时间的DataFrame
df_dates = pd.DataFrame({'Date': dates})
print("DataFrame with dates:")
print(df_dates)
DataFrame with dates:
Date
0 2024-01-01
1 2024-01-02
2 2024-01-03
3 2024-01-04
4 2024-01-05
6.2 重采样和频率转换
重采样是指将时间序列数据从一个频率转换为另一个频率的过程,例如从天到月或从分钟到小时。
resample()
函数的常用参数及其含义:
-
rule
: 指定重采样的频率,可以是字符串表示的频率别名(如’D’表示天,'M’表示月),也可以是DateOffset
、Timedelta
或Offset
对象。例如,'D’表示每日,'M’表示每月,'W’表示每周。默认为None。 -
on
: 指定包含时间序列数据的列名。如果时间序列数据是DataFrame的索引,则不需要使用on
参数。但如果时间序列数据是DataFrame的一个普通列,则需要使用on
参数来指定这个列的名称。 -
axis
: 指定重采样的方向,0表示对行进行重采样,1表示对列进行重采样。默认为0。 -
closed
: 指定重采样区间的闭合方式,'right’表示右闭合,'left’表示左闭合,None表示不指定闭合。默认为None。 -
label
: 控制聚合后的标签选择方式,'right’表示使用区间的右侧标签作为标签,'left’表示使用区间的左侧标签作为标签,None表示不指定标签。默认为None。 -
convention
: 控制聚合时边界的处理方式,'start’表示使用左侧的边界,‘end’表示使用右侧的边界。默认为’start’。 -
kind
: 指定聚合时的计算方式,'period’表示以每个区间的开始时间为索引进行聚合,'timestamp’表示以每个区间的中心时间为索引进行聚合。默认为None。 -
loffset
: 对于聚合结果的索引偏移量,用于调整聚合结果的索引。默认为None。 -
base
: 控制聚合周期相对于时间点的基准,对于周期为N的聚合,'0’表示聚合周期相对于时间点的起始位置,'1’表示相对于时间点的终止位置。默认为0。
# 将时间序列数据从天转换为月
df_monthly = df_dates.resample('M', on='Date').sum()
在上面的例子中,df_dates
是一个DataFrame,其中包含一个名为Date
的列,该列包含时间序列数据。因此,我们使用了on='Date'
参数来指定Date
列作为时间序列数据的来源列。
6.3 移动窗口统计
移动窗口统在上面数据统计部分我们已经提到过,但是它也可以用在在时间序列数据上执行滑动窗口计法,例如计算移动平均值或移动总和。
# 计算移动平均值
rolling_mean = df_dates.rolling(window=2).mean()