Pandas数据分析学习笔记

前言

开刷Pandas数据分析,看起来很好理解,不过没做笔记没敲代码心里总是不安稳,所以复现下课程代码并演示其中遇到的问题,顺便水一水笔记好了

一、数据读取

0. 数据类型

数据类型说明Pandas读取方法
csv, tsv, txt用逗号、tab或其它字符分割的文本文件read_csv
excelxls或xlsx文件read_excel
mysql关系型数据表read_sql

1. read_csv

1.1 读取csv文件

csv是以逗号分割的文本文件,如下:

userId,movieId,rating,timestamp
1,1,4.0,964982703
1,3,4.0,964981247
1,6,4.0,964982224
1,47,5.0,964983815

直接使用read_csv读取该文件

fpath = "../datas/ml-latest-small/ratings.csv"
# 读取
ratings = pd.read_csv(fpath)

1.2 指定分割符

已知access_pvuv.txt如下:

2019-09-10  139    92
2019-09-09  185    153
2019-09-08  123    59
2019-09-07  65     40
2019-09-06  157    98
2019-09-05  205    151
2019-09-04  196    167
2019-09-03  216    176
2019-09-02  227    148
2019-09-01  105    61

为read_csv添加参数delimiter (或seq) 指定分隔符,header=None表示没有第一行列名称

fpath = "../datas/crazyant/access_pvuv.txt"

pvuv = pd.read_csv(
    fpath,
    delimiter='\t',
    header=None,
    names=['date', 'pv', 'uv']
)

2. read_excel

fpath = "../datas/crazyant/access_pvuv.xlsx"
pvuv = pd.read_excel(fpath)
print(pvuv)

'''
输出结果
           日期   PV   UV
0  2019-09-10  139   92
1  2019-09-09  185  153
2  2019-09-08  123   59
3  2019-09-07   65   40
4  2019-09-06  157   98
5  2019-09-05  205  151
6  2019-09-04  196  167
7  2019-09-03  216  176
8  2019-09-02  227  148
9  2019-09-01  105   61
'''

3. read_sql

3.1 使用pymysql

连接数据库,选择编码方式

import pandas as pd
import pymysql

conn = pymysql.connect(
    host='localhost',
    user='root',
    password='password',
    database='dbname',
    charset='utf8'
)

table = pd.read_sql("select * from tbname", con=conn)
print(table)
'''
输出结果
   id                       preorder_traversal_string
0   1             4_2_1_0_#_#_#_3_#_#_8_7_#_#_11_#_#_
1   2  5_4_2_#_#_1_7_#_6_#_#_#_3_0_#_5_1_#_#_#_6_#_#_
2   3                  6_#_7_5_3_#_#_1_#_#_2_8_#_#_#_
'''

但是会报警告:

UserWarning: pandas only supports SQLAlchemy connectable (engine/connection) or database string URI or sqlite3 DBAPI2 connection. Other DBAPI2 objects are not tested. Please consider using SQLAlchemy.

这里建议我们使用SQLAlchemy

3.2 使用SQLAlchemy

import pandas as pd

from sqlalchemy import create_engine

host = "127.0.0.1"
user = "root"
password = "password"
database = "dbname"

engine = create_engine(f"mysql+pymysql://{user}:{password}@{host}/{database}")
sql = 'select * from tbname'
table = pd.read_sql(sql=sql, con=engine)

print(table)
'''
输出结果
   id                       preorder_traversal_string
0   1             4_2_1_0_#_#_#_3_#_#_8_7_#_#_11_#_#_
1   2  5_4_2_#_#_1_7_#_6_#_#_#_3_0_#_5_1_#_#_#_6_#_#_
2   3                  6_#_7_5_3_#_#_1_#_#_2_8_#_#_#_
'''

4. 查看数据格式

# 查看前几行数据,默认为5行
print(ratings.head())
'''
输出结果
   userId  movieId  rating  timestamp
0       1        1     4.0  964982703
1       1        3     4.0  964981247
2       1        6     4.0  964982224
3       1       47     5.0  964983815
4       1       50     5.0  964982931
'''

# 查看数据的形状,返回(行数、列数)
print(ratings.shape)

'''
输出结果
(100836, 4)
'''

# 查看列名列表
print(ratings.columns)
'''
输出结果
Index(['userId', 'movieId', 'rating', 'timestamp'], dtype='object')
'''

# 查看索引列
print(ratings.index)
'''
输出结果
RangeIndex(start=0, stop=100836, step=1)
'''

# 查看每列的数据类型
print(ratings.dtypes)
'''
输出结果
userId         int64
movieId        int64
rating       float64
timestamp      int64
dtype: object
'''

二、数据结构

1. Series

import pandas as pd

# 创建Series
s1 = pd.Series(list('abcd'))
print(s1)
'''
0    a
1    b
2    c
3    d
dtype: object
'''

# 指定索引创建Series
s2 = pd.Series(list('efgh'), index=list('abcd'))
print(s2)
print(s2.index)
'''
a    e
b    f
c    g
d    h
dtype: object
Index(['a', 'b', 'c', 'd'], dtype='object')
'''

# 字典创建Series
dict = {
    'a': 'e',
    'b': 'f',
    'c': 'g',
    'd': 'h'
}
s3 = pd.Series(dict)
print(s3)
'''
a    e
b    f
c    g
d    h
dtype: object
'''

2. DataFrame

import pandas as pd

# 字典创建DataFrame
data = {
        'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
        'year': [2000, 2001, 2002, 2001, 2002],
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9]
    }
df = pd.DataFrame(data)

print(df)
'''
    state  year  pop
0    Ohio  2000  1.5
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9
'''

# 输出DataFrame的索引、列标签以及数据类型
print(df.index, '\n\n', df.columns, '\n\n', df.dtypes)
'''
RangeIndex(start=0, stop=5, step=1)

 Index(['state', 'year', 'pop'], dtype='object')

 state     object
year       int64
pop      float64
dtype: object
'''

三、查询数据

0. 查询方法

  1. df.loc :基于标签索引,结果包含最后一个标签的值
  2. df.iloc:基于位置索引,结果不包含最后一个位置的值
  3. df.where
  4. df.query

本节主要介绍df.loc

1. 数据预处理

import pandas as pd

# 数据预处理
df = pd.read_csv("../datas/beijing_tianqi/beijing_tianqi_2018.csv")

print(df.head())
'''
          ymd bWendu yWendu tianqi fengxiang fengli  aqi aqiInfo  aqiLevel
0  2018-01-01     3℃    -6℃   晴~多云       东北风   1-2级   59       良         2
1  2018-01-02     2℃    -5℃   阴~多云       东北风   1-2级   49       优         1
2  2018-01-03     2℃    -5℃     多云        北风   1-2级   28       优         1
3  2018-01-04     0℃    -8℃      阴       东北风   1-2级   28       优         1
4  2018-01-05     3℃    -6℃   多云~晴       西北风   1-2级   50       优   
'''

# 设定索引为日期,方便按日期筛选
df.set_index('ymd', inplace=True)

# 替换掉温度的后缀℃
df.loc[:, "bWendu"] = df["bWendu"].str.replace("℃", "").astype('int32')
df.loc[:, "yWendu"] = df["yWendu"].str.replace("℃", "").astype('int32')
# df[df.columns["bWendu"]] = df["bWendu"].str.replace("℃", "").astype('int32')
# df[df.columns["yWendu"]] = df["yWendu"].str.replace("℃", "").astype('int32')

print(df.head())
'''
            bWendu  yWendu tianqi fengxiang fengli  aqi aqiInfo  aqiLevel
ymd
2018-01-01       3      -6   晴~多云       东北风   1-2级   59       良         2
2018-01-02       2      -5   阴~多云       东北风   1-2级   49       优         1
2018-01-03       2      -5     多云        北风   1-2级   28       优         1
2018-01-04       0      -8      阴       东北风   1-2级   28       优         1
2018-01-05       3      -6   多云~晴       西北风   1-2级   50       优    
'''

这里会报一个警告:

 DeprecationWarning: In a future version, `df.iloc[:, i] = newvals` will attempt to set the 
 values inplace instead of always setting a new array. To retain the old behavior, use either
 `df[df.columns[i]] = newvals` or, if columns are non-unique, `df.isetitem(i, newvals)`

2. 按数值、列表、区间查询

# 得到单个值
single_value = df.loc['2018-01-03', 'bWendu']

# 得到一列/一行
s1 = df.loc['2018-01-03', ['bWendu', 'yWendu']]
s2 = df.loc[['2018-01-03', '2018-01-04', '2018-01-05'], 'bWendu']

# 得到DataFrame
df2 = df.loc[['2018-01-03','2018-01-04','2018-01-05'], ['bWendu', 'yWendu']]

# 按区间查询
df3 = df.loc['2018-01-03':'2018-01-05', 'bWendu':'fengxiang']

3. 条件查询

# 查询最高温度小于30度,并且最低温度大于15度,并且是晴天,并且天气为优的数据
df4 = df.loc[(df["bWendu"] <= 30) & (df["yWendu"] >= 15)
        & (df["tianqi"] == '晴') & (df["aqiLevel"] == 1), :]
print(df4)
'''
            bWendu  yWendu tianqi fengxiang fengli  aqi aqiInfo  aqiLevel
ymd
2018-08-24      30      20      晴        北风   1-2级   40       优         1
2018-09-07      27      16      晴       西北风   3-4级   22       优         1
'''

其中,条件表达式返回的是一个布尔值的Series

# 观察条件表达式
print(df["yWendu"] < -10)
'''
2018-01-01    False
2018-01-02    False
2018-01-03    False
2018-01-04    False
2018-01-05    False
              ...
2018-12-27     True
2018-12-28     True
2018-12-29     True
2018-12-30     True
2018-12-31    False
Name: yWendu, Length: 365, dtype: bool
'''

4. 函数查询

# 直接写lambda表达式
df5 = df.loc[lambda df : (df["bWendu"] <= 30) & (df["yWendu"] >= 15), :]

# 编写自己的函数,查询9月份,空气质量好的数据
def query_my_data(df):
    return df.index.str.startswith("2018-09") & (df["aqiLevel"] == 1)

df6 = df.loc[query_my_data, :]

四、新增数据列

1. 直接赋值

df.loc[:, 'wencha'] = df['bWendu'] - df['yWendu']

2. df.apply

传入一个函数并选定axis:

  1. 当axis=1,函数的参数为一行的Series(常用)
  2. 当axis=0,函数的参数为一列的Series
def get_wendu_type(x):
    if x["bWendu"] > 33:
        return '高温'
    if x["yWendu"] < -10:
        return '低温'
    return '常温'

df.loc[:, "wendu_type"] = df.apply(get_wendu_type, axis=1)

3. df.assign

df.assign总是会创建一个新的copy

利用lambda表达式,处理原来的数据得到新列

# 可以同时添加多个新的列
df.assign(
    yWendu_huashi = lambda x : x["yWendu"] * 9 / 5 + 32,
    # 摄氏度转华氏度
    bWendu_huashi = lambda x : x["bWendu"] * 9 / 5 + 32
)

4. 条件选择分组后赋值

# 先创建空列(这是第一种创建新列的方法)
df['wencha_type'] = ''

错误示例:

df.loc[df["bWendu"]-df["yWendu"]>10]["wencha_type"] = "温差大"

df.loc[df["bWendu"]-df["yWendu"]<=10]["wencha_type"] = "温差正常"

两个[]的链式操作相当于

df.get(condition).set(wen_cha)

这里get得到的结果可能是view也可能是copy,存在歧义

正确示范:

df.loc[df["bWendu"]-df["yWendu"]>10, "wencha_type"] = "温差大"

df.loc[df["bWendu"]-df["yWendu"]<=10, "wencha_type"] = "温差正常"

五、聚合查询

1. describe输出统计结果

# 一下子提取所有数字列统计结果
df.describe()

           bWendu      yWendu         aqi    aqiLevel      wencha
count  365.000000  365.000000  365.000000  365.000000  365.000000
mean    18.665753    8.358904   82.183562    2.090411   10.306849
std     11.858046   11.755053   51.936159    1.029798    2.781233
min     -5.000000  -12.000000   21.000000    1.000000    2.000000
25%      8.000000   -3.000000   46.000000    1.000000    8.000000
50%     21.000000    8.000000   69.000000    2.000000   10.000000
75%     29.000000   19.000000  104.000000    3.000000   12.000000
max     38.000000   27.000000  387.000000    6.000000   18.000000

describe只能得到数值列的统计结果

2. 非数值列统计

2.1 unique唯一去重

print(df['tianqi'].unique())

['晴~多云' '阴~多云' '多云' '阴' '多云~晴' '多云~阴' '晴' '阴~小雪' '小雪~多云' '小雨~ 阴' '小雨~雨夹雪'
 '多云~小雨' '小雨~多云' '大雨~小雨' '小雨' '阴~小雨' '多云~雷阵雨' '雷阵雨~多云' '阴~ 雷阵雨' '雷阵雨'
 '雷阵雨~大雨' '中雨~雷阵雨' '小雨~大雨' '暴雨~雷阵雨' '雷阵雨~中雨' '小雨~雷阵雨' '雷 阵雨~阴' '中雨~小雨'
 '小雨~中雨' '雾~多云' '霾']

2.2 value_counts按值计数

print(df['wencha_type'].value_counts())

温差正常    187
温差大     178
Name: wencha_type, dtype: int64

3. 协方差和相关系数

print(df.cov(), '\n\n', df.corr())

              bWendu      yWendu          aqi   aqiLevel     wencha
bWendu    140.613247  135.529633    47.462622   0.879204   5.083614
yWendu    135.529633  138.181274    16.186685   0.264165  -2.651641
aqi        47.462622   16.186685  2697.364564  50.749842  31.275937
aqiLevel    0.879204    0.264165    50.749842   1.060485   0.615038
wencha      5.083614   -2.651641    31.275937   0.615038   7.735255

             bWendu    yWendu       aqi  aqiLevel    wencha
bWendu    1.000000  0.972292  0.077067  0.071999  0.154142
yWendu    0.972292  1.000000  0.026513  0.021822 -0.081106
aqi       0.077067  0.026513  1.000000  0.948883  0.216523
aqiLevel  0.071999  0.021822  0.948883  1.000000  0.214740
wencha    0.154142 -0.081106  0.216523  0.214740  1.000000

六、缺失值处理

1. 处理方式

Pandas使用这些函数处理缺失值:

  • isnull和notnull:检测是否是空值,可用于df和series
  • dropna:丢弃、删除缺失值
    • axis : 删除行还是列,{0 or ‘index’, 1 or ‘columns’}, default 0
    • how : 如果等于any则任何值为空都删除,如果等于all则所有值都为空才删除
    • inplace : 如果为True则修改当前df,否则返回新的df
  • fillna:填充空值
    • value:用于填充的值,可以是单个值,或者字典(key是列名,value是值)
    • method : 等于ffill使用前一个不为空的值填充forword fill;等于bfill使用后一个不为空的值填充backword fill
    • axis : 按行还是列填充,{0 or ‘index’, 1 or ‘columns’}
    • inplace : 如果为True则修改当前df,否则返回新的df

2. 数据清洗示例

image.png

2.1 检测空值

# 跳过前面两空行
studf = pd.read_excel("../datas/student_excel/student_excel.xlsx", skiprows=2)

# 检测空值
print(studf.isnull())

    Unnamed: 0     姓名     科目     分数
0         True  False  False  False
1         True   True  False  False
2         True   True  False  False
3         True   True   True   True
4         True  False  False  False
5         True   True  False   True
6         True   True  False  False
7         True   True   True   True
8         True  False  False  False
9         True   True  False  False
10        True   True  False  False

2.2 dropna示例

# 删除全为空的行和列
studf.dropna(axis=1, how='all', inplace=True)
studf.dropna(axis=0, how='all', inplace=True)

print(studf)

     姓名  科目    分数
0    小明  语文  85.0
1   NaN  数学  80.0
2   NaN  英语  90.0
4    小王  语文  85.0
5   NaN  数学   NaN
6   NaN  英语  90.0
8    小刚  语文  85.0
9   NaN  数学  80.0
10  NaN  英语  90.0

2.3 fillna示例

# 将空的分数填充为0
# 将空的姓名填充为上一个值
studf['分数'].fillna(value=0, inplace=True)
studf['姓名'].fillna(method='ffill', inplace=True)

print(studf)

    姓名  科目    分数
0   小明  语文  85.0
1   小明  数学  80.0
2   小明  英语  90.0
4   小王  语文  85.0
5   小王  数学   0.0
6   小王  英语  90.0
8   小刚  语文  85.0
9   小刚  数学  80.0
10  小刚  英语  90.0

七、数据排序

1. 排序方法

  1. Series的排序:
    Series.sort_values(ascending=True, inplace=False)
    参数说明:
  • ascending:默认为True升序排序,为False降序排序
  • inplace:是否修改原始Series
  1. DataFrame的排序:
    DataFrame.sort_values(by, ascending=True, inplace=False)
    参数说明:
  • by:字符串或者List<字符串>,单列排序或者多列排序
  • ascending:bool或者bool的列表,升序还是降序,如果是list对应by的多列
  • inplace:是否修改原始DataFrame

2. 排序示例

# Series的排序
print(df['aqi'].sort_values())

ymd
2018-09-29     21
2018-10-09     21
2018-09-07     22
2018-09-30     22
2018-10-29     22
             ...
2018-11-14    266
2018-03-13    287
2018-04-02    287
2018-03-14    293
2018-03-28    387
Name: aqi, Length: 365, dtype: int64

# DataFrame的排序
df.sort_values(by=['aqi', 'bWendu'], ascending=[False, True], inplace=True)
print(df[['aqi', 'bWendu']])

            aqi  bWendu
ymd
2018-03-28  387      25
2018-03-14  293      15
2018-03-13  287      17
2018-04-02  287      26
2018-11-14  266      13
...         ...     ...
2018-10-29   22      15
2018-09-30   22      19
2018-09-07   22      27
2018-10-09   21      15
2018-09-29   21      22

八、字符串处理

0. Pandas的str

Pandas的字符串处理:

  1. 使用方法:先获取Series的str属性,然后在属性上调用函数;
  2. 只能在字符串列上使用,不能数字列上使用;
  3. Dataframe上没有str属性和处理方法
  4. Series.str并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似;

1. 基础用法

获取str属性,并调用各种方法,如replace, isnumeric, len

print(df['wencha_type'].str.len())

ymd
2018-03-28    3
2018-03-14    4
2018-03-13    3
2018-04-02    3
2018-11-14    4
             ..
2018-10-29    3
2018-09-30    4
2018-09-07    3
2018-10-09    3
2018-09-29    3
Name: wencha_type, Length: 365, dtype: int64

2. 条件查询

或使用contains, startswith等得到bool的Series做条件查询

print(df.loc[df['tianqi'].str.startswith('多云'), ['tianqi', 'fengxiang']])

           tianqi fengxiang
ymd
2018-03-28   多云~晴        东风
2018-03-14   多云~阴       东北风
2018-04-02     多云        北风
2018-11-14     多云        南风
2018-11-26     多云       东南风
...           ...       ...
2018-01-25     多云       东北风
2018-10-10   多云~晴       西北风
2018-02-03     多云        北风
2018-09-30     多云       西北风
2018-10-09   多云~晴       西北风

3. 正则表达式

由于Series.str天然支持正则表达式,示例如下:

匹配字符集合并做替换:

# 添加新列
def get_nianyueri(x):
    year,month,day = x["ymd"].split("-")
    return f"{year}年{month}月{day}日"
df["中文日期"] = df.apply(get_nianyueri, axis=1)

# 尝试将 年 月 日 去除
df.loc[:, '中文日期'] = df['中文日期'].str.replace('[年月日]', '')
print(df['中文日期'])

86     20180328
72     20180314
71     20180313
91     20180402
317    20181114
         ...
301    20181029
272    20180930
249    20180907
281    20181009
271    20180929
Name: 中文日期, Length: 365, dtype: object

捕获组提取数据:

extracted_fengli = df['fengli'].str.extract(r'(\d)-(\d)')
print(extracted_fengli.head())

     0  1
86   1  2
72   1  2
71   1  2
91   1  2
317  1  2
..  .. ..
301  3  4
272  4  5
249  3  4
281  4  5
271  3  4

九、索引

0. 索引的作用

选择恰当的索引可以加速查询性能

  1. 当索引是唯一的时,Pandas会用哈希表优化性能,时间复杂度为O(1)
  2. 当索引不唯一,但是单调时,Pandas会使用二分查找,时间复杂度为O(log n)
  3. 当索引既不唯一且不单调时,Pandas只能遍历,时间复杂度为O(n)

因此,我们要判断当前索引是否为以上类型,尽可能选择唯一的索引,单调次之

1. 选择索引示例

原始数据如下:

print(df.head())

   userId  movieId  rating  timestamp
0       1        1     4.0  964982703
1       1        3     4.0  964981247
2       1        6     4.0  964982224
3       1       47     5.0  964983815
4       1       50     5.0  964982931

判断每一列是否存在唯一约束:

print(df.nunique() == len(df))

userId       False
movieId      False
rating       False
timestamp    False
dtype: bool

判断每一列是否单调:


# 使用这一句会报FutureWarning
# is_monotonic = df.apply(lambda x: x.is_monotonic)

is_monotonic_increasing = df.apply(lambda x: x.is_monotonic_increasing)
is_monotonic_decreasing = df.apply(lambda x: x.is_monotonic_decreasing)
print(is_monotonic_increasing, '\n\n', is_monotonic_decreasing)

userId        True
movieId      False
rating       False
timestamp    False
dtype: bool

 userId       False
movieId      False
rating       False
timestamp    False
dtype: bool

2. 设置索引示例

DataFrame.set_index(keys, append=False, drop=True, inplace=False)

keys代表被用作索引的列

append代表是否保留原来的索引

drop表示是否将指定的列在原数据列中删除

inplace表示是否在原数据上修改

df.set_index('userId',append=True, drop=False, inplace=True)
print(df.head())

          userId  movieId  rating  timestamp
  userId
0 1            1        1     4.0  964982703
1 1            1        3     4.0  964981247
2 1            1        6     4.0  964982224
3 1            1       47     5.0  964983815
4 1            1       50     5.0  964982931

关于Python学习指南

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

包括:Python激活码+安装包、Python web开发,Python爬虫,Python数据分析,人工智能、自动化办公等学习教程。带你从零基础系统性的学好Python!

👉Python所有方向的学习路线👈

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。(全套教程文末领取)

在这里插入图片描述

👉Python学习视频600合集👈

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

在这里插入图片描述

温馨提示:篇幅有限,已打包文件夹,获取方式在:文末

👉Python70个实战练手案例&源码👈

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

在这里插入图片描述

👉Python大厂面试资料👈

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

在这里插入图片描述

在这里插入图片描述

👉Python副业兼职路线&方法👈

学好 Python 不论是就业还是做副业赚钱都不错,但要学会兼职接单还是要有一个学习规划。

在这里插入图片描述

👉 这份完整版的Python全套学习资料已经上传,朋友们如果需要可以扫描下方CSDN官方认证二维码免费领取保证100%免费

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值