• 基于Python的数据科学(7):Pandas基础


    介绍

            Pandas 是一个强大的Python库,专为数据操作和分析而设计。Pandas 提供了高效的数据结构和数据分析工具,特别适合处理带有标签的数据。本文将详细介绍Pandas的基本功能和用法。

    安装与导入

            首先,确保你已经安装了Pandas库,如果没有安装,可以使用pip命令进行安装:

    pip install pandas
    

            然后,在你的Python脚本中导入Pandas:

    1. import pandas as pd
    2. pd.__version__

    Pandas数据结构

            Pandas主要有两种数据结构:Series和DataFrame。Series是一维数组,DataFrame是二维数组。接下来我们将详细介绍这两种数据结构。

    Series

    创建Series

            Series可以通过列表或数组创建:

    1. data_pd = pd.Series([0.25, 0.5, 0.75, 1.0])
    2. print("Pandas series from list: \n", data_pd)
    3. numpy_arr = np.arange(5)
    4. data_pd = pd.Series(numpy_arr)
    5. print("Pandas series from numpy array: \n", data_pd)

    Series属性

            Series对象有许多有用的属性:

    1. print("Data values: ", data_pd.values)
    2. print("Data index: ", data_pd.index)

    Series索引

    1. print("Data[1]: ", data_pd[1])
    2. print("Data[-2:]: \n", data_pd[-2:])
    3. data_pd = pd.Series([0.25, 0.5, 0.75, 1.0], index=['a', 'b', 'c', 'd'])
    4. print("Data['b']: ", data_pd['b'])
    5. index = ['a', 'b', 'c', 'd', 3]
    6. data_pd = pd.Series(numpy_arr, index=index)
    7. print("Index['a']: ", data_pd['a'])
    8. print("Index[3]: ", data_pd[3])

    Pandas和字典

    1. some_population_dict = {'Chiangrai': 11111, 'Pathum Thani': 22222, 'Bangkok': 33333, 'Chiangmai': 44444}
    2. data_pd = pd.Series(some_population_dict)
    3. print("Population['Bangkok']: ", data_pd['Bangkok'])
    4. print("Population['Pathumthan':'Chiangmai']: \n", data_pd['Pathum Thani': 'Chiangmai'])

    操作Series

    1. data_pd['e'] = 99
    2. print("Data with e: \n", data_pd)
    3. print("a in data?: ", 'a' in data_pd)
    4. print("All keys: ", data_pd.keys())
    5. print("All items: ", list(data_pd.items()))
    6. print("All values: ", data_pd.values)
    7. print("Data[(data > 0.3) & (data < 0.8)]: \n", data_pd[(data_pd > 0.3) & (data_pd < 0.8)])
    8. print("Data[['a', 'e']]: \n", data_pd[['a', 'e']])

    iloc 和 loc

    1. data = pd.Series(['a', 'b', 'c'], index=(1, 3, 5))
    2. print("Data[1]: ", data[1])
    3. print("Data[1:3]: \n", data[1:3])
    4. print("Data loc [1]: ", data.loc[1])
    5. print("Data loc [1:3]: \n", data.loc[1:3])
    6. print("Data iloc [1]: ", data.iloc[1])
    7. print("Data iloc [1:3]: \n", data.iloc[1:3])

    DataFrame

    创建DataFrame

            DataFrame是一种二维数组,可以通过多个方式创建,例如从字典、列表或Numpy数组。

    1. some_population_dict = {'Chiangrai': 11111, 'Pathum Thani': 22222, 'Bangkok': 33333, 'Chiangmai': 44444}
    2. some_area_dict = {'Chiangrai': 999, 'Pathum Thani': 888, 'Bangkok': 777, 'Chiangmai': 666, 'Syria': 333}
    3. states = pd.DataFrame({'population': some_population_dict, 'area': some_area_dict})
    4. print("Everything: ")
    5. print(states)

    DataFrame索引

    1. print("Only Chiangrai to Bangkok: ")
    2. print(states['Chiangrai': 'Bangkok'])
    3. print("Only population column: ")
    4. print(states['Chiangrai': 'Bangkok']['population'])
    5. print(states['population']['Chiangrai': 'Bangkok'])
    6. print("Only area column with everything")
    7. print(states['area'])
    8. print(states[:]['area'])

    DataFrame属性

    1. print("Index: ", states.index)
    2. print("Index[-1]: ", states.index[-1])
    3. print("Columns: ", states.columns)
    4. print("Columns[0:1]: ", states.columns[0:1])

    其他创建方式

    1. population_series = pd.Series(some_population_dict)
    2. pd_from_series = pd.DataFrame(population_series, columns=['population'])
    3. print("PD from series: \n", pd_from_series)
    4. data = [{'a': i, 'b': 2 * i} for i in range(3)]
    5. pd_from_list_dict = pd.DataFrame(data, index=[1, 2, 3])
    6. print("PD from list of dict: \n", pd_from_list_dict)
    7. data_numpy = np.random.rand(3, 2)
    8. index = ['a', 'b', 'c']
    9. columns = ['foo', 'bar']
    10. pd_from_numpy = pd.DataFrame(data_numpy, index=index, columns=columns)
    11. print("PD from numpy: \n", pd_from_numpy)

    操作DataFrame

    1. data['density'] = data['pop'] / data['area']
    2. print(data)
    3. print("==First row using iloc==")
    4. print(data.iloc[0])
    5. print("==First three rows, first two columns using iloc==")
    6. print(data.iloc[:3, :2])
    7. print("==Use loc for explicit index==")
    8. print(data.loc[:'Bangkok', :'pop'])
    9. print("==chain iloc and loc==")
    10. print(data.loc[:'Bangkok'].iloc[:, :2])
    11. print("==masking + fancy==")
    12. print(data.loc[data.density > 20, ['pop', 'density']])

    数据处理

    处理缺失数据

    1. import numpy as np
    2. print("==Fill na with 0==")
    3. print(df.fillna(0))
    4. print("==Fill all na with mean==")
    5. print(df.fillna(df.mean()))
    6. print("replace df.mean() for col 1 with in place")
    7. df[1].fillna(df[1].mean(), inplace=True)
    8. print(df)
    9. print("==Interpolate==")
    10. print(df.interpolate(method='values'))

    连接数据

    1. data_numpy = np.random.rand(3, 2)
    2. index = ['Bangkok', 'Chiangmai', 'Samut Prakan']
    3. columns = ['Population', 'Area']
    4. pd_from_numpy = pd.DataFrame(data_numpy, index=index, columns=columns)
    5. print("==First dataframe==")
    6. print(pd_from_numpy)
    7. data_numpy2 = np.random.rand(4, 3)
    8. index2 = ['Bangkok', 'Chiangmai', 'Samut Prakan', 'Pathum Thani']
    9. columns2 = ['HDI', 'Temperature', 'GDP']
    10. pd_from_numpy2 = pd.DataFrame(data_numpy2, index=index2, columns=columns2)
    11. print("==Second dataframe==")
    12. print(pd_from_numpy2)
    13. print("==Normal concat along axis 1==")
    14. print(pd.concat([pd_from_numpy, pd_from_numpy2], axis=1))
    15. print("==Concat with join inner==")
    16. print(pd.concat([pd_from_numpy, pd_from_numpy2], axis=1, join='inner'))

    合并数据

    1. left = pd.DataFrame({'ID': ['001', '002', '003', '005'], 'DS': ['B', 'B', 'B', 'C+'], 'SAD': ['A', 'B', 'C+', 'F']})
    2. right = pd.DataFrame({'ID': ['001', '002', '003', '004'], 'HCI': ['B+', 'A', 'A', 'B+'], 'SDQI': ['A', 'A', 'B+', 'B']})
    3. result = pd.merge(left, right, on='ID')
    4. print(result)
    5. result = pd.merge(left, right, on='ID', how="outer")
    6. print(result)
    7. result = pd.merge(left, right, on='ID', how="left")
    8. print(result)

    聚合数据

    1. df = pd.DataFrame([('bird', 'Falconiformes', 389.0), ('bird', 'Psittaciformes', 24.0), ('mammal', 'Carnivora', 80.2), ('mammal', 'Primates', np.nan), ('mammal', 'Carnivora', 58)], index=['falcon', 'parrot', 'lion', 'monkey', 'leopard'], columns=('class', 'order', 'max_speed'))
    2. grouped = df.groupby('class')
    3. print(grouped.sum())
    4. grouped = df.groupby('order')
    5. print(grouped.sum())
    6. grouped = df.groupby(['class', 'order'])
    7. print(grouped.sum())
    8. print(df.groupby(['class'])['max_speed'].median())
    9. import seaborn as sns
    10. planets = sns.load_dataset('planets')
    11. print(planets.groupby('method').sum())
    12. print(planets.groupby('method')['orbital_period'].median())

    时间序列

            Pandas提供了强大的时间序列处理功能,可以方便地进行时间序列的操作和分析。

    创建时间序列

    1. date = pd.to_datetime("2015-07-04")
    2. print(type(date))
    3. date.strftime('%A')
    4. date + pd.to_timedelta(np.arange(12), 'D')
    5. index = pd.to_datetime(['2014-07-04', '2014-08-04', '2015-07-04', '2015-08-04'])
    6. data = pd.DataFrame(np.random.rand(4,2), index=index, columns=['Apple', 'Orange'])
    7. print(data)
    8. print(data['2014-07-04':'2015-07-04'])
    9. print(data['2015'])

    时间序列操作

    1. pd.date_range('2015-07-03', '2015-07-10')
    2. pd.date_range('2015-07-03', periods = 8)
    3. pd.date_range('2015-07-03', periods = 8, freq='H')
    4. pd.date_range('2015-07-03', periods = 18, freq='MS')
    5. pd.date_range('2015-07-03', periods = 18, freq='2H30T')

    股票数据示例

    1. from pandas_datareader import data
    2. import matplotlib.pyplot as plt
    3. goog = data.DataReader('GOOG', start='2004', end='2016', data_source='yahoo')
    4. goog_close = goog['Close']
    5. goog_close.plot()
    6. goog_close.plot(alpha=0.2, style='-')
    7. goog_close.resample('BA').mean().plot(style='o')
    8. goog_close.asfreq('BA').plot(style='--')

    滚动窗口

    1. rolling = goog_close.rolling(365, center = True)
    2. data = pd.DataFrame({'input': goog_close, 'one_year rolling mean': rolling.mean(), 'one_year rolling std': rolling.std()})
    3. data.plot(style=['-', '--', ':'])

    自行车统计数据示例

    1. data = pd.read_csv('data/FremontBridge.csv', index_col='Date', parse_dates=True)
    2. data.columns = ['West', 'East']
    3. data['Total'] = data['East'] + data['West']
    4. data.fillna(0, inplace=True)
    5. weekly = data.resample('W').agg('sum')
    6. weekly.plot(style=[":", "--", '-'])
    7. plt.ylabel('Weekly bicycle count')
    8. by_time = data.groupby(data.index.time).mean()
    9. by_time.plot()
    10. by_day = data.groupby(data.index.dayofweek).mean()
    11. by_day.index = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
    12. by_day.plot(style=[':', '--', '-'])

    任务 1

    1. 将数据文件夹中的 "howlongwelive.csv" 文件加载到 DataFrame 中 提示:Reproducibility Tips: Absolute vs. relative paths | Kaggle

    2. 打印前两行和最后两行数据

    3. 打印 DataFrame 的形状

    4. 打印特征(列)名称

    5. 使用 .describe() 打印数据摘要

    6. 由于 Hepatatis B 列有很多空值,并且与 Diptheria 高度相关,删除 Hepatatis 列。另外,由于 Population 列有太多空值,也将其删除

    7. 将 Status 转换为 0 或 1(0 表示 Developing,1 表示 Developed)

    8. 将列名 thinness 1-19 years 重命名为 thinness 10-19 years

    9. 获取除 Life Expectancy 外的所有列,并转换为名为 X 的 numpy 数组

    10. 获取 Life Expectancy 列并转换为名为 y 的 numpy 数组

    1. import pandas as pd
    2. # 1. 将数据文件夹中的 "howlongwelive.csv" 文件加载到 DataFrame 中
    3. df = pd.read_csv('data/howlongwelive.csv')
    4. # 2. 打印前两行和最后两行数据
    5. print("前两行数据:")
    6. print(df.head(2))
    7. print("最后两行数据:")
    8. print(df.tail(2))
    9. # 3. 打印 DataFrame 的形状
    10. print("DataFrame 的形状:", df.shape)
    11. # 4. 打印特征(列)名称
    12. print("特征(列)名称:", df.columns)
    13. # 5. 使用 .describe() 打印数据摘要
    14. print("数据摘要:")
    15. print(df.describe())
    16. # 6. 由于 Hepatatis B 列有很多空值,并且与 Diptheria 高度相关,删除 Hepatatis 列。另外,由于 Population 列有太多空值,也将其删除
    17. df.drop(['Hepatatis B', 'Population'], axis=1, inplace=True)
    18. # 7. 将 Status 转换为 0 或 1(0 表示 Developing,1 表示 Developed)
    19. df['Status'] = df['Status'].apply(lambda x: 0 if x == 'Developing' else 1)
    20. # 8. 将列名 thinness 1-19 years 重命名为 thinness 10-19 years
    21. df.rename(columns={'thinness 1-19 years': 'thinness 10-19 years'}, inplace=True)
    22. # 9. 获取除 Life Expectancy 外的所有列,并转换为名为 X 的 numpy 数组
    23. X = df.drop('Life expectancy ', axis=1).values
    24. # 10. 获取 Life Expectancy 列并转换为名为 y 的 numpy 数组
    25. y = df['Life expectancy '].values

    处理缺失数据

    np.nan

    1. import numpy as np
    2. print("np.nan 的类型:", type(np.nan))
    3. print("np.nan 减 1 的结果:", np.nan - 1) # 任何与 nan 进行的运算结果仍然是 nan
    4. vals2 = np.array([1, np.nan, 3, 4])
    5. print("Sum:", vals2.sum())
    6. print("Nansum:", np.nansum(vals2))
    7. print("Nanmin:", np.nanmin(vals2))
    8. print("Nanmax:", np.nanmax(vals2))

    创建包含 np.nan 和 None 的 pd.Series

    1. import pandas as pd
    2. dfs = pd.Series([1, None, np.nan])
    3. print("Pandas 自动将 None 转换为 nan")
    4. print(dfs)
    5. dfs = pd.Series(["Hello", None, np.nan])
    6. print("Pandas 不会转换,因为字符串是对象")
    7. print(dfs)
    8. dfs = pd.Series([True, None, np.nan])
    9. print("Pandas 不会转换,布尔值被强制转换为对象")
    10. print(dfs)

    检查空值

    1. dfs = pd.Series([1, np.nan, "hello", None])
    2. print("是否为空值:", dfs.isnull())

    仅显示非空数据

    1. print("仅显示非空数据")
    2. print(dfs[dfs.notnull()])

    删除空值

    1. print("删除所有空值")
    2. print(dfs.dropna()) # 这不是就地操作
    3. print(dfs) # 这将返回旧的副本
    4. # 删除包含空值的列,使用 axis = 1
    5. df = pd.DataFrame([[1, np.nan, 2],
    6. [2, 3, 5],
    7. [np.nan, 4, np.nan],
    8. [4, np.nan, np.nan]])
    9. print(df.dropna(axis=1)) # 默认 axis = 0
    10. # 如果所有值都是 nan,则删除列
    11. df[3] = np.nan # 创建新列
    12. print(df.dropna(axis=1, how="all"))

    用值填充空值

    1. # 用 0 填充所有空值
    2. print("用 0 填充所有空值")
    3. print(df.fillna(0)) # 这不是就地操作
    4. # 用平均值填充所有空值
    5. print("用平均值填充所有空值")
    6. print(df.fillna(df.mean()))
    7. # 用平均值替换第 1 列的缺失值并就地操作
    8. df[1].fillna(df[1].mean(), inplace=True)
    9. print(df)
    10. # 用插值法填充缺失值
    11. print("用插值法填充缺失值")
    12. print(df.interpolate(method='values'))

    合并数据集

    1. data_numpy = np.random.rand(3, 2) # 形状为 3x2
    2. index = ['Bangkok', 'Chiangmai', 'Samut Prakan']
    3. columns = ['Population', 'Area']
    4. pd_from_numpy = pd.DataFrame(data_numpy, index=index, columns=columns)
    5. print("第一个 DataFrame:")
    6. print(pd_from_numpy)
    7. data_numpy2 = np.random.rand(4, 3)
    8. index2 = ['Bangkok', 'Chiangmai', 'Samut Prakan', 'Pathum Thani']
    9. columns2 = ['HDI', 'Temperature', 'GDP']
    10. pd_from_numpy2 = pd.DataFrame(data_numpy2, index=index2, columns=columns2)
    11. print("第二个 DataFrame:")
    12. print(pd_from_numpy2)
    13. # 正常连接(沿轴 1)
    14. print("沿轴 1 正常连接:")
    15. print(pd.concat([pd_from_numpy, pd_from_numpy2], axis=1)) # 默认 join='outer',即完全外连接
    16. # 内连接
    17. print("内连接:")
    18. print(pd.concat([pd_from_numpy, pd_from_numpy2], axis=1, join='inner'))

    基于ID合并数据集

    1. left = pd.DataFrame({'ID': ['001', '002', '003', '005'],
    2. 'DS': ['B', 'B', 'B', 'C+'],
    3. 'SAD': ['A', 'B', 'C+', 'F']})
    4. print("左表:")
    5. print(left)
    6. right = pd.DataFrame({'ID': ['001', '002', '003', '004'],
    7. 'HCI': ['B+', 'A', 'A', 'B+'],
    8. 'SDQI': ['A', 'A', 'B+', 'B']})
    9. print("右表:")
    10. print(right)
    11. # 内连接
    12. result = pd.merge(left, right, on='ID') # 默认 how='inner'
    13. print("内连接结果:")
    14. print(result)
    15. # 外连接
    16. result = pd.merge(left, right, on='ID', how="outer")
    17. print("外连接结果:")
    18. print(result)
    19. # 左连接
    20. result = pd.merge(left, right, on='ID', how="left")
    21. print("左连接结果:")
    22. print(result)

    聚合

    1. df = pd.DataFrame([('bird', 'Falconiformes', 389.0),
    2. ('bird', 'Psittaciformes', 24.0),
    3. ('mammal', 'Carnivora', 80.2),
    4. ('mammal', 'Primates', np.nan),
    5. ('mammal', 'Carnivora', 58)],
    6. index=['falcon', 'parrot', 'lion', 'monkey', 'leopard'],
    7. columns=('class', 'order', 'max_speed'))
    8. print("DataFrame:")
    9. print(df)
    10. grouped = df.groupby('class') # 返回一个 DataFrameGroupBy 对象
    11. print("按 class 分组求和:")
    12. print(grouped.sum())
    13. grouped = df.groupby('order')
    14. print("按 order 分组求和:")
    15. print(grouped.sum())
    16. grouped = df.groupby(['class', 'order'])
    17. print("按 class 和 order 分组求和:")
    18. print(grouped.sum())
    19. print("按 class 分组求中位数:")
    20. print(df.groupby(['class'])['max_speed'].median())

    任务 2

    1. 继续使用 "howlongwelive.csv" 文件,检查每列有多少缺失数据
    2. 使用均值填充所有缺失数据
    3. 按国家进行分组。哪个国家的平均预期寿命最低/最高?
    4. 按状态进行分组。发达国家和发展中国家的预期寿命是否有显著差异?
    5. 手动创建另一个包含两列的数据框。第一列是与国家列相同的 ID 列。还添加另一列 Noise_level,并填充随机值(随意填写)。
    6. 根据 ID 列合并这两个数据集。
    1. import pandas as pd
    2. import numpy as np
    3. # 1. 继续使用 "howlongwelive.csv" 文件,检查每列有多少缺失数据
    4. df = pd.read_csv('data/howlongwelive.csv')
    5. print("每列缺失数据的数量:")
    6. print(df.isnull().sum())
    7. # 2. 使用均值填充所有缺失数据
    8. df.fillna(df.mean(), inplace=True)
    9. # 3. 按国家分组,计算平均预期寿命
    10. grouped_by_country = df.groupby('Country')['Life expectancy '].mean()
    11. print("平均预期寿命最低的国家:", grouped_by_country.idxmin(), grouped_by_country.min())
    12. print("平均预期寿命最高的国家:", grouped_by_country.idxmax(), grouped_by_country.max())
    13. # 4. 按状态分组,计算平均预期寿命
    14. grouped_by_status = df.groupby('Status')['Life expectancy '].mean()
    15. print("按状态分组的平均预期寿命:")
    16. print(grouped_by_status)
    17. # 5. 创建另一个包含两列的数据框
    18. noise_level = np.random.rand(len(df['Country'].unique()))
    19. additional_df = pd.DataFrame({'Country': df['Country'].unique(), 'Noise_level': noise_level})
    20. # 6. 根据 ID 列合并这两个数据集
    21. merged_df = pd.merge(df, additional_df, on='Country')
    22. print("合并后的 DataFrame:")
    23. print(merged_df.head())

    时间序列

            Pandas 是在金融建模的背景下开发的,因此它包含了一整套处理日期、时间和时间索引数据的工具。首先让我们了解 Python 如何处理日期和时间。

    1. from datetime import datetime
    2. datetime(year=2025, month=7, day=4)

            使用 dateutil 模块,可以从各种字符串格式解析日期。

    1. from dateutil import parser
    2. date = parser.parse("4th of July, 2015")
    3. date

            一旦你有了一个 datetime 对象,就可以做一些事情,比如打印星期几:

    date.strftime('%A, %D')
    

            我们可以类似地创建 numpy 类型的日期时间,它是一种非常有效的存储日期时间的方法。

    1. date = np.array('2015-07-04', dtype=np.datetime64) # ISO 日期
    2. date

            由于其 numpy 类型,我们可以快速对其进行矢量化操作。

    date + np.arange(12)
    

            Pandas 使用 Timestamp 对象,它结合了 datetime 和 dateutil 的易用性以及 numpy.datetime64 的高效存储和矢量化接口。从这些 Timestamp 对象组中,Pandas 可以构建 DatetimeIndex,可用于索引 Series 或 DataFrame 中的数据。

    1. import pandas as pd
    2. date = pd.to_datetime("2015-07-04")
    3. print(type(date))
    4. date.strftime('%A')

            使用 pd.to_timedelta 可以执行 numpy 风格的矢量化操作。

    date + pd.to_timedelta(np.arange(12), 'D')  # 单位是纳秒,不支持 Y 和 M,因为每个月的纳秒数不相等
    

            当你开始通过时间戳索引数据时,Pandas 的时间序列工具真正变得有用。例如,我们可以构建一个具有时间索引数据的 Series 对象:

    1. index = pd.to_datetime(['2014-07-04', '2014-08-04', '2015-07-04', '2015-08-04'])
    2. data = pd.DataFrame(np.random.rand(4, 2), index=index, columns=['Apple', 'Orange'])
    3. data

            使用切片访问行:

    data['2014-07-04':'2015-07-04']
    

            有特殊的日期索引,例如传递年份:

    data['2015']
    

            一个有用的方法是 date_range,它生成从指定开始和结束的日期:

    pd.date_range('2015-07-03', '2015-07-10')
    

            我们可以指定周期而不是结束:

    pd.date_range('2015-07-03', periods=8)
    

            如果我们想要 8 个周期,但以小时为单位,我们使用 freq 参数:

    pd.date_range('2015-07-03', periods=8, freq='H')
    

    股票

    1. from pandas_datareader import data
    2. goog = data.DataReader('GOOG', start='2004', end='2016', data_source='yahoo')
    3. goog.head()
    4. import matplotlib.pyplot as plt
    5. goog_close = goog['Close']
    6. goog_close.plot()

            时间序列数据的一个常见需求是以更高或更低的频率重新采样。这可以使用 resample() 方法,或更简单的 asfreq() 方法来完成。这两者之间的主要区别是 resample() 本质上是数据聚合,而 asfreq() 本质上是数据选择。

            让我们看看 Google 收盘价,当我们对数据进行降采样时,两者返回的结果有什么不同。在这里,我们将在营业年末对数据进行重新采样:

    resample
    1. goog_close.plot(alpha=0.2, style='-')
    2. goog_close.resample('BA').mean().plot(style='o') # BA = 营业年末
    3. goog_close.asfreq('BA').plot(style='--')

            请注意区别:在每个点,resample 报告前一年的平均值,而 asfreq 报告年末的值。

            橙色点表示 goog_close.resample(),绿色虚线表示 goog_close.asfreq()。

            resample 和 asfreq 之间的区别:

    1. ts = pd.Series(range(365), index=pd.date_range(start='20190101', end='20191231', freq='D'))
    2. ts.head()
    ts.asfreq(freq='Q')  # 季度
    

            这不是每个季度的平均值,而是每个季度最后一天的平均值:

            Pandas 有两个密切相关的方法:shift() 和 tshift()。简而言之,两者的区别在于 shift() 移动数据,而 tshift() 移动索引。在两种情况下,移动是以频率的倍数指定的。这里我们将同时移动 900 天:

    1. fig, ax = plt.subplots(3, sharey=True)
    2. goog_close = goog_close.asfreq('D', method='pad')
    3. goog_close.plot(ax=ax[0])
    4. goog_close.shift(900).plot(ax=ax[1])
    5. goog_close.tshift(900).plot(ax=ax[2])

            为什么要移动?

            一个常见的上下文是计算一段时间内的差异。例如,我们使用移动后的值来计算 Google 股票在数据集期间的一年投资回报率:

    1. ROI = 100 * (goog_close.tshift(-365) / goog_close)
    2. ROI.plot()
    3. plt.ylabel('Return on Investment')

            这有助于我们看到 Google 股票的整体趋势:迄今为止,投资 Google 最有利可图的时间是其 IPO 后不久和 2009 年中期的经济衰退。

    滚动窗口

    1. rolling = goog_close.rolling(365, center=True)
    2. rolling
    3. data = pd.DataFrame({'input': goog_close, 'one_year rolling mean': rolling.mean(), 'one_year rolling std': rolling.std()})
    4. data.plot(style=['-', '--', ':'])

    自行车计数

            示例:可视化西雅图自行车计数

    1. data = pd.read_csv('data/FremontBridge.csv')
    2. data = pd.read_csv('data/FremontBridge.csv', index_col='Date', parse_dates=True)
    3. data.head()
    4. data.columns = ['West', 'East']
    5. data.head()
    6. data.isna().sum()
    7. data.fillna(0, inplace=True)
    8. data['Total'] = data['East'] + data['West']
    9. data.head()

    任务 3

    1. 加载 "data/appl_1980_2014.csv" 到数据框 df 中
    2. 将 Date 列转换为 datetime 类型
    3. 然后仅筛选年份不小于 1987 的数据
    4. 按升序排序索引(最早的日期在前)- 使用 sort_index
    5. 我们想知道苹果在每个月底的表现,因此获取每列的平均值,并在每个月的最后一个营业日进行重新采样(即 BM)
    6. 顺便说一下,我们的数据中有多少个月?
    7. 比较今年和去年 High 列的差异,使用 shift(),其中差异为 this_year - last_year。绘制此图,x 轴为日期,y 轴为涨跌幅
    8. 对 Close 列执行窗口大小为 100 天的滚动平均线
    9. 使用以下代码加载微软数据:
    1. import pandas as pd
    2. import matplotlib.pyplot as plt
    3. from pandas_datareader import data
    4. # 1. 加载 "data/appl_1980_2014.csv" 文件
    5. df = pd.read_csv('data/appl_1980_2014.csv')
    6. # 2. 将 Date 列转换为 datetime 类型
    7. df['Date'] = pd.to_datetime(df['Date'])
    8. # 3. 过滤掉年份小于 1987 的数据
    9. df = df[df['Date'].dt.year >= 1987]
    10. # 4. 按升序排序索引(最早的日期在前)
    11. df.sort_index(ascending=True, inplace=True)
    12. # 5. 获取每列的平均值,在每个月的最后一个工作日进行重采样(即 BM)
    13. monthly_avg = df.resample('BM', on='Date').mean()
    14. # 6. 我们的数据中有多少个月?
    15. num_months = len(monthly_avg)
    16. print(f"数据中的月份数量: {num_months}")
    17. # 7. 使用 shift() 比较今年与去年 High 列的差异,绘制图表
    18. monthly_avg['High_diff'] = monthly_avg['High'].diff(12)
    19. plt.figure(figsize=(10, 6))
    20. plt.plot(monthly_avg.index, monthly_avg['High_diff'], label='High Difference')
    21. plt.xlabel('Date')
    22. plt.ylabel('Difference in High')
    23. plt.title('Year-over-Year Difference in High Price')
    24. plt.legend()
    25. plt.show()
    26. # 8. 对 Close 列执行窗口大小为 100 天的滚动平均
    27. df['Close_MA100'] = df['Close'].rolling(window=100).mean()
    28. plt.figure(figsize=(10, 6))
    29. plt.plot(df['Date'], df['Close'], label='Close Price')
    30. plt.plot(df['Date'], df['Close_MA100'], label='100-Day Moving Average')
    31. plt.xlabel('Date')
    32. plt.ylabel('Price')
    33. plt.title('Apple Close Price and 100-Day Moving Average')
    34. plt.legend()
    35. plt.show()
    36. # 9. 加载微软数据并比较回报率
    37. microsoft = data.DataReader('MSFT', start='1987', end='2014', data_source='yahoo')
    38. apple_2000_onward = df[df['Date'].dt.year >= 2000].copy()
    39. microsoft_2000_onward = microsoft[microsoft.index.year >= 2000].copy()
    40. apple_2000_onward['Return'] = apple_2000_onward['Close'] / apple_2000_onward['Close'].iloc[0]
    41. microsoft_2000_onward['Return'] = microsoft_2000_onward['Close'] / microsoft_2000_onward['Close'].iloc[0]
    42. plt.figure(figsize=(10, 6))
    43. plt.plot(apple_2000_onward['Date'], apple_2000_onward['Return'], label='Apple Return')
    44. plt.plot(microsoft_2000_onward.index, microsoft_2000_onward['Return'], label='Microsoft Return')
    45. plt.xlabel('Date')
    46. plt.ylabel('Return Rate')
    47. plt.title('Apple vs Microsoft Return Rate (2000 Onward)')
    48. plt.legend()
    49. plt.show()

    结语

            在本篇文章中,我们详细介绍了 Pandas 的基础知识,包括 Series 和 DataFrame 的创建、索引、切片、合并和聚合操作等。我们通过实际的代码示例演示了如何使用 Pandas 进行数据处理和分析,并完成了几个实际任务,以帮助大家更好地理解和掌握这些操作。

            通过这些内容,我们可以看到 Pandas 强大的数据处理能力,它不仅能够处理结构化数据,还能够与其他科学计算库(如 NumPy)无缝集成。Pandas 提供的这些功能,使得我们能够更高效地进行数据清洗、转换和分析,从而在数据科学项目中发挥重要作用。

            下一篇文章将介绍数据可视化工具——Matplotlib。我们将学习如何使用Matplotlib创建各种图表,以更直观地展示数据分析的结果。敬请期待!

    如果你觉得这篇博文对你有帮助,请点赞、收藏、关注我,并且可以打赏支持我!

    欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。

    谢谢大家的支持!

  • 相关阅读:
    虚拟化技术基础
    pytorch autograd 自动微分
    JavaWeb开发之——SQL简介&通用语法及分类(05)
    DSPE-PEG-Aldehyde DSPE-PEG-CHO 磷脂-聚乙二醇-醛基疏水18碳磷脂
    【数据库之postgreSQL】全文索引之飞快
    Mysql以key-val存储、正常存储的区别
    MyBatis-plus组件学习
    常用的git指令
    刘二大人 PyTorch深度学习实践 笔记 P11 卷积神经网络(高级篇)
    LayaBox---TypeScript---三斜线指令
  • 原文地址:https://blog.csdn.net/ljd939952281/article/details/140967446