第6章 缺失数据

第6章 缺失数据

在接下来的两章中,会接触到数据预处理中比较麻烦的类型,即缺失数据和文本数据(尤其是混杂型文本)
Pandas在步入1.0后,对数据类型也做出了新的尝试,尤其是Nullable类型和String类型,了解这些可能在未来成为主流的新特性是必要的
import pandas as pd
import numpy as np
df = pd.read_csv('data/table_missing.csv')
df.head()
SchoolClassIDGenderAddressHeightWeightMathPhysics
0S_1C_1NaNMstreet_1173NaN34.0A+
1S_1C_1NaNFstreet_2192NaN32.5B+
2S_1C_11103.0Mstreet_2186NaN87.2B+
3S_1NaNNaNFstreet_216781.080.4NaN
4S_1C_11105.0NaNstreet_415964.084.8A-

一、缺失观测及其类型

1. 了解缺失信息

(a)isna和notna方法
对Series使用会返回布尔列表
df['Physics'].isna().head()
0    False
1    False
2    False
3     True
4    False
Name: Physics, dtype: bool
df['Physics'].notna().head()
0     True
1     True
2     True
3    False
4     True
Name: Physics, dtype: bool
对DataFrame使用会返回布尔表
df.isna().head()
SchoolClassIDGenderAddressHeightWeightMathPhysics
0FalseFalseTrueFalseFalseFalseTrueFalseFalse
1FalseFalseTrueFalseFalseFalseTrueFalseFalse
2FalseFalseFalseFalseFalseFalseTrueFalseFalse
3FalseTrueTrueFalseFalseFalseFalseFalseTrue
4FalseFalseFalseTrueFalseFalseFalseFalseFalse
但对于DataFrame我们更关心到底每列有多少缺失值
df.isna().sum()
School      0
Class       4
ID          6
Gender      7
Address     0
Height      0
Weight     13
Math        5
Physics     4
dtype: int64
此外,可以通过第1章中介绍的info函数查看缺失信息
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 35 entries, 0 to 34
Data columns (total 9 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   School   35 non-null     object 
 1   Class    31 non-null     object 
 2   ID       29 non-null     float64
 3   Gender   28 non-null     object 
 4   Address  35 non-null     object 
 5   Height   35 non-null     int64  
 6   Weight   22 non-null     float64
 7   Math     30 non-null     float64
 8   Physics  31 non-null     object 
dtypes: float64(3), int64(1), object(5)
memory usage: 2.6+ KB
(b)查看缺失值的所以在行
以最后一列为例,挑出该列缺失值的行
df[df['Physics'].isna()]
SchoolClassIDGenderAddressHeightWeightMathPhysics
3S_1NaNNaNFstreet_216781.080.4NaN
8S_1C_21204.0Fstreet_516263.033.8NaN
13S_1C_31304.0NaNstreet_219570.085.2NaN
22S_2C_22203.0Mstreet_415591.073.8NaN
(c)挑选出所有非缺失值列
使用all就是全部非缺失值,如果是any就是至少有一个不是缺失值
df[df.notna().all(1)]
SchoolClassIDGenderAddressHeightWeightMathPhysics
5S_1C_21201.0Mstreet_515968.097.0A-
6S_1C_21202.0Fstreet_417694.063.5B-
12S_1C_31303.0Mstreet_718882.049.7B
17S_2C_12103.0Mstreet_415761.052.5B-
21S_2C_22202.0Fstreet_719477.068.5B+
25S_2C_32301.0Fstreet_415778.072.3B+
27S_2C_32303.0Fstreet_719099.065.9C
28S_2C_32304.0Fstreet_616481.095.5A-
29S_2C_32305.0Mstreet_418773.048.9B

2. 三种缺失符号

(a)np.nan
np.nan是一个麻烦的东西,首先它不等与任何东西,甚至不等于自己
np.nan == np.nan
False
np.nan == 0
False
np.nan == None
False
在用equals函数比较时,自动略过两侧全是np.nan的单元格,因此结果不会影响
df.equals(df)
True
其次,它在numpy中的类型为浮点,由此导致数据集读入时,即使原来是整数的列,只要有缺失值就会变为浮点型
type(np.nan)
float
pd.Series([1,2,3]).dtype
dtype('int64')
pd.Series([1,np.nan,3]).dtype
dtype('float64')
此外,对于布尔类型的列表,如果是np.nan填充,那么它的值会自动变为True而不是False
pd.Series([1,np.nan,3],dtype='bool')
0    True
1    True
2    True
dtype: bool
但当修改一个布尔列表时,会改变列表类型,而不是赋值为True
s = pd.Series([True,False],dtype='bool')
s[1]=np.nan
s
0    1.0
1    NaN
dtype: float64
在所有的表格读取后,无论列是存放什么类型的数据,默认的缺失值全为np.nan类型
因此整型列转为浮点;而字符由于无法转化为浮点,因此只能归并为object类型(‘O’),原来是浮点型的则类型不变
df['ID'].dtype
dtype('float64')
df['Math'].dtype
dtype('float64')
df['Class'].dtype
dtype('O')
(b)None
None比前者稍微好些,至少它会等于自身
None == None
True
它的布尔值为False
pd.Series([None],dtype='bool')
0    False
dtype: bool
修改布尔列表不会改变数据类型
s = pd.Series([True,False],dtype='bool')
s[0]=None
s
0    False
1    False
dtype: bool
s = pd.Series([1,0],dtype='bool')
s[0]=None
s
0    False
1    False
dtype: bool
在传入数值类型后,会自动变为np.nan
type(pd.Series([1,None])[1])
numpy.float64
只有当传入object类型是保持不动,几乎可以认为,除非人工命名None,它基本不会自动出现在Pandas中
type(pd.Series([1,None],dtype='O')[1])
NoneType
在使用equals函数时不会被略过,因此下面的情况下返回False
pd.Series([None]).equals(pd.Series([np.nan]))
False
(c)NaT
NaT是针对时间序列的缺失值,是Pandas的内置类型,可以完全看做时序版本的np.nan,与自己不等,且使用equals是也会被跳过
s_time = pd.Series([pd.Timestamp('20120101')]*5)
s_time
0   2012-01-01
1   2012-01-01
2   2012-01-01
3   2012-01-01
4   2012-01-01
dtype: datetime64[ns]
s_time[2] = None
s_time
0   2012-01-01
1   2012-01-01
2          NaT
3   2012-01-01
4   2012-01-01
dtype: datetime64[ns]
s_time[2] = np.nan
s_time
0   2012-01-01
1   2012-01-01
2          NaT
3   2012-01-01
4   2012-01-01
dtype: datetime64[ns]
s_time[2] = pd.NaT
s_time
0   2012-01-01
1   2012-01-01
2          NaT
3   2012-01-01
4   2012-01-01
dtype: datetime64[ns]
type(s_time[2])
pandas._libs.tslibs.nattype.NaTType
s_time[2] == s_time[2]
False
s_time.equals(s_time)
True
s = pd.Series([True,False],dtype='bool')
s[1]=pd.NaT
s
0    True
1    True
dtype: bool

3. Nullable类型与NA符号

这是Pandas在1.0新版本中引入的重大改变,其目的就是为了(在若干版本后)解决之前出现的混乱局面,统一缺失值处理方法
“The goal of pd.NA is provide a “missing” indicator that can be used consistently across data types (instead of np.nan, None or pd.NaT depending on the data type).”——User Guide for Pandas v-1.0
官方鼓励用户使用新的数据类型和缺失类型pd.NA
(a)Nullable整形
对于该种类型而言,它与原来标记int上的符号区别在于首字母大写:‘Int’
s_original = pd.Series([1, 2], dtype="int64")
s_original
0    1
1    2
dtype: int64
s_new = pd.Series([1, 2], dtype="Int64")
s_new
0    1
1    2
dtype: Int64
它的好处就在于,其中前面提到的三种缺失值都会被替换为统一的NA符号,且不改变数据类型
s_original[1] = np.nan
s_original
0    1.0
1    NaN
dtype: float64
s_new[1] = np.nan
s_new
0       1
1    <NA>
dtype: Int64
s_new[1] = None
s_new
0       1
1    <NA>
dtype: Int64
s_new[1] = pd.NaT
s_new
0       1
1    <NA>
dtype: Int64
(b)Nullable布尔
对于该种类型而言,作用与上面的类似,记号为boolean
s_original = pd.Series([1, 0], dtype="bool")
s_original
0     True
1    False
dtype: bool
s_new = pd.Series([0, 1], dtype="boolean")
s_new
0    False
1     True
dtype: boolean
s_original[0] = np.nan
s_original
0    NaN
1    0.0
dtype: float64
s_original = pd.Series([1, 0], dtype="bool") #此处重新加一句是因为前面赋值改变了bool类型
s_original[0] = None
s_original
0    False
1    False
dtype: bool
s_new[0] = np.nan
s_new
0    <NA>
1    True
dtype: boolean
s_new[0] = None
s_new
0    <NA>
1    True
dtype: boolean
s_new[0] = pd.NaT
s_new
0    <NA>
1    True
dtype: boolean
需要注意的是,含有pd.NA的布尔列表在1.0.2之前的版本作为索引时会报错,这是一个之前的bug,现已经修复
s = pd.Series(['dog','cat'])
s[s_new]
1    cat
dtype: object
(c)string类型
该类型是1.0的一大创新,目的之一就是为了区分开原本含糊不清的object类型,这里将简要地提及string,因为它是第7章的主题内容
它本质上也属于Nullable类型,因为并不会因为含有缺失而改变类型
s = pd.Series(['dog','cat'],dtype='string')
s
0    dog
1    cat
dtype: string
s[0] = np.nan
s
0    <NA>
1     cat
dtype: string
s[0] = None
s
0    <NA>
1     cat
dtype: string
s[0] = pd.NaT
s
0    <NA>
1     cat
dtype: string
此外,和object类型的一点重要区别就在于,在调用字符方法后,string类型返回的是Nullable类型,object则会根据缺失类型和数据类型而改变
s = pd.Series(["a", None, "b"], dtype="string")
s.str.count('a')
0       1
1    <NA>
2       0
dtype: Int64
s2 = pd.Series(["a", None, "b"], dtype="object")
s2.str.count("a")
0    1.0
1    NaN
2    0.0
dtype: float64
s.str.isdigit()
0    False
1     <NA>
2    False
dtype: boolean
s2.str.isdigit()
0    False
1     None
2    False
dtype: object

4. NA的特性

(a)逻辑运算
只需看该逻辑运算的结果是否依赖pd.NA的取值,如果依赖,则结果还是NA,如果不依赖,则直接计算结果
True | pd.NA
True
pd.NA | True
True
False | pd.NA
<NA>
False & pd.NA
False
True & pd.NA
<NA>
取值不明直接报错
#bool(pd.NA)
(b)算术运算和比较运算
这里只需记住除了下面两类情况,其他结果都是NA即可
pd.NA ** 0
1
1 ** pd.NA
1
其他情况:
pd.NA + 1
<NA>
"a" * pd.NA
<NA>
pd.NA == pd.NA
<NA>
pd.NA < 2.5
<NA>
np.log(pd.NA)
<NA>
np.add(pd.NA, 1)
<NA>

5. convert_dtypes方法

这个函数的功能往往就是在读取数据时,就把数据列转为Nullable类型,是1.0的新函数
pd.read_csv('data/table_missing.csv').dtypes
School      object
Class       object
ID         float64
Gender      object
Address     object
Height       int64
Weight     float64
Math       float64
Physics     object
dtype: object
pd.read_csv('data/table_missing.csv').convert_dtypes().dtypes
School      string
Class       string
ID           Int64
Gender      string
Address     string
Height       Int64
Weight       Int64
Math       float64
Physics     string
dtype: object

二、缺失数据的运算与分组

1. 加号与乘号规则

使用加法时,缺失值为0
s = pd.Series([2,3,np.nan,4])
s.sum()
9.0
使用乘法时,缺失值为1
s.prod()
24.0
使用累计函数时,缺失值自动略过
s.cumsum()
0    2.0
1    5.0
2    NaN
3    9.0
dtype: float64
s.cumprod()
0     2.0
1     6.0
2     NaN
3    24.0
dtype: float64
s.pct_change()
0         NaN
1    0.500000
2    0.000000
3    0.333333
dtype: float64

2. groupby方法中的缺失值

自动忽略为缺失值的组
df_g = pd.DataFrame({'one':['A','B','C','D',np.nan],'two':np.random.randn(5)})
df_g
onetwo
0A-1.126645
1B0.924595
2C-2.076309
3D-0.312150
4NaN0.961543
df_g.groupby('one').groups
{'A': Int64Index([0], dtype='int64'),
 'B': Int64Index([1], dtype='int64'),
 'C': Int64Index([2], dtype='int64'),
 'D': Int64Index([3], dtype='int64')}

三、填充与剔除

1. fillna方法

(a)值填充与前后向填充(分别与ffill方法和bfill方法等价)
df['Physics'].fillna('missing').head()
0         A+
1         B+
2         B+
3    missing
4         A-
Name: Physics, dtype: object
df['Physics'].fillna(method='ffill').head()
0    A+
1    B+
2    B+
3    B+
4    A-
Name: Physics, dtype: object
df['Physics'].fillna(method='backfill').head()
0    A+
1    B+
2    B+
3    A-
4    A-
Name: Physics, dtype: object
(b)填充中的对齐特性
df_f = pd.DataFrame({'A':[1,3,np.nan],'B':[2,4,np.nan],'C':[3,5,np.nan]})
df_f.fillna(df_f.mean())
ABC
01.02.03.0
13.04.05.0
22.03.04.0
返回的结果中没有C,根据对齐特点不会被填充
df_f.fillna(df_f.mean()[['A','B']])
ABC
01.02.03.0
13.04.05.0
22.03.0NaN

2. dropna方法

(a)axis参数
df_d = pd.DataFrame({'A':[np.nan,np.nan,np.nan],'B':[np.nan,3,2],'C':[3,2,1]})
df_d
ABC
0NaNNaN3
1NaN3.02
2NaN2.01
df_d.dropna(axis=0)
ABC
df_d.dropna(axis=1)
C
03
12
21
(b)how参数(可以选all或者any,表示全为缺失去除和存在缺失去除)
df_d.dropna(axis=1,how='all')
BC
0NaN3
13.02
22.01
(c)subset参数(即在某一组列范围中搜索缺失值)
df_d.dropna(axis=0,subset=['B','C'])
ABC
1NaN3.02
2NaN2.01

四、插值(interpolation)

1. 线性插值

(a)索引无关的线性插值
默认状态下,interpolate会对缺失的值进行线性插值
s = pd.Series([1,10,15,-5,-2,np.nan,np.nan,28])
s
0     1.0
1    10.0
2    15.0
3    -5.0
4    -2.0
5     NaN
6     NaN
7    28.0
dtype: float64
s.interpolate()
0     1.0
1    10.0
2    15.0
3    -5.0
4    -2.0
5     8.0
6    18.0
7    28.0
dtype: float64
s.interpolate().plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7fe7df20af50>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EtBT3Tjk-1592926632370)(output_146_1.png)]

此时的插值与索引无关
s.index = np.sort(np.random.randint(50,300,8))
s.interpolate()
#值不变
69      1.0
71     10.0
84     15.0
117    -5.0
119    -2.0
171     8.0
219    18.0
236    28.0
dtype: float64
s.interpolate().plot()
#后面三个点不是线性的(如果几乎为线性函数,请重新运行上面的一个代码块,这是随机性导致的)
<matplotlib.axes._subplots.AxesSubplot at 0x7fe7dfc69890>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qL2XqiKA-1592926632373)(output_149_1.png)]

(b)与索引有关的插值
method中的index和time选项可以使插值线性地依赖索引,即插值为索引的线性函数
s.interpolate(method='index').plot()
#可以看到与上面的区别
<matplotlib.axes._subplots.AxesSubplot at 0x7fe7dca0c4d0>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QqdA4QaT-1592926632375)(output_151_1.png)]

如果索引是时间,那么可以按照时间长短插值,对于时间序列将在第9章详细介绍
s_t = pd.Series([0,np.nan,10]
        ,index=[pd.Timestamp('2012-05-01'),pd.Timestamp('2012-05-07'),pd.Timestamp('2012-06-03')])
s_t
2012-05-01     0.0
2012-05-07     NaN
2012-06-03    10.0
dtype: float64
s_t.interpolate().plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7fe7dc964850>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-grj5NI74-1592926632376)(output_154_1.png)]

s_t.interpolate(method='time').plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7fe7dc8eda10>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jDGLsjS2-1592926632377)(output_155_1.png)]

2. 高级插值方法

此处的高级指的是与线性插值相比较,例如样条插值、多项式插值、阿基玛插值等(需要安装Scipy),方法详情请看这里
关于这部分仅给出一个官方的例子,因为插值方法是数值分析的内容,而不是Pandas中的基本知识:
ser = pd.Series(np.arange(1, 10.1, .25) ** 2 + np.random.randn(37))
missing = np.array([4, 13, 14, 15, 16, 17, 18, 20, 29])
ser[missing] = np.nan
methods = ['linear', 'quadratic', 'cubic']
df = pd.DataFrame({m: ser.interpolate(method=m) for m in methods})
df.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7fe7dc86f810>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bVEG5Bb-1592926632378)(output_157_1.png)]

3. interpolate中的限制参数

(a)limit表示最多插入多少个
s = pd.Series([1,np.nan,np.nan,np.nan,5])
s.interpolate(limit=2)
0    1.0
1    2.0
2    3.0
3    NaN
4    5.0
dtype: float64
(b)limit_direction表示插值方向,可选forward,backward,both,默认前向
s = pd.Series([np.nan,np.nan,1,np.nan,np.nan,np.nan,5,np.nan,np.nan,])
s.interpolate(limit_direction='backward')
0    1.0
1    1.0
2    1.0
3    2.0
4    3.0
5    4.0
6    5.0
7    NaN
8    NaN
dtype: float64
(c)limit_area表示插值区域,可选inside,outside,默认None
s = pd.Series([np.nan,np.nan,1,np.nan,np.nan,np.nan,5,np.nan,np.nan,])
s.interpolate(limit_area='inside')
0    NaN
1    NaN
2    1.0
3    2.0
4    3.0
5    4.0
6    5.0
7    NaN
8    NaN
dtype: float64
s = pd.Series([np.nan,np.nan,1,np.nan,np.nan,np.nan,5,np.nan,np.nan,])
s.interpolate(limit_area='outside')
0    NaN
1    NaN
2    1.0
3    NaN
4    NaN
5    NaN
6    5.0
7    5.0
8    5.0
dtype: float64

五、问题与练习

1. 问题

【问题一】 如何删除缺失值占比超过25%的列?
d[d/d.shape[0]<=0.75].index.tolist()
['A', 'B']
df_d = pd.DataFrame({'A':[np.nan,np.nan,np.nan],'B':[np.nan,3,2],'C':[3,2,1]})
d = df_d.count()
df_d.drop((d[d/d.shape[0]<=0.75]).index.tolist(),axis=1)
C
03
12
21
【问题二】 什么是Nullable类型?请谈谈为什么要引入这个设计?

其目的就是为了(在若干版本后)解决之前出现的混乱局面,统一缺失值处理方法
“The goal of pd.NA is provide a “missing” indicator that can be used consistently across data types (instead of np.nan, None or pd.NaT depending on the data type).”——User Guide for Pandas v-1.0
官方鼓励用户使用新的数据类型和缺失类型pd.NA
它的好处就在于,其中前面提到的三种缺失值都会被替换为统一的NA符号,且不改变数据类型

【问题三】 对于一份有缺失值的数据,可以采取哪些策略或方法深化对它的了解?

观察分布情况,可进行填充,删除等操作

2. 练习

【练习一】现有一份虚拟数据集,列类型分别为string/浮点/整型,请解决如下问题:
(a)请以列类型读入数据,并选出C为缺失值的行。
(b)现需要将A中的部分单元转为缺失值,单元格中的最小转换概率为25%,且概率大小与所在行B列单元的值成正比。
data = pd.read_csv('data/Missing_data_one.csv').head()
data.head()
ABC
0not_NaN0.9224.0
1not_NaN0.700NaN
2not_NaN0.5038.0
3not_NaN0.9384.0
4not_NaN0.95210.0
#(a)
data[data['C'].isnull()]
ABC
1not_NaN0.7NaN
#(b)
import random
data.loc[:,'A'][data['B'].map(lambda x: True if x > random.random()else False)]=np.nan
data
ABC
0NaN0.9224.0
1not_NaN0.700NaN
2NaN0.5038.0
3NaN0.9384.0
4NaN0.95210.0
【练习二】 现有一份缺失的数据集,记录了36个人来自的地区、身高、体重、年龄和工资,请解决如下问题:
(a)统计各列缺失的比例并选出在后三列中至少有两个非缺失值的行。
(b)请结合身高列和地区列中的数据,对体重进行合理插值。
data1 = pd.read_csv('data/Missing_data_two.csv')
data1.head()
编号地区身高体重年龄工资
01A157.50NaN47.015905.0
12B202.0091.8025.0NaN
23C169.0962.18NaNNaN
34A166.6159.9577.05434.0
45B185.19NaN62.04242.0
#(a)
data1.isnull().sum()/data1.shape[0]

编号    0.000000
地区    0.000000
身高    0.000000
体重    0.222222
年龄    0.250000
工资    0.222222
dtype: float64
data1[data1.iloc[:,-3:].isnull().sum(axis=1)>1]
编号地区身高体重年龄工资
23C169.0962.18NaNNaN
1112A202.5692.30NaNNaN
1213C177.37NaN79.0NaN
1415C199.1189.20NaNNaN
2627B158.28NaN51.0NaN
3233C181.01NaNNaN13021.0
3334A196.6787.00NaNNaN
#(b)
data1.loc[:,'体重'] = data1.set_index('身高')['体重'].interpolate(method='index').reset_index()
data1
编号地区身高体重年龄工资
01A157.50NaN47.015905.0
12B202.0091.8025.0NaN
23C169.0962.18NaNNaN
34A166.6159.9577.05434.0
45B185.1972.4262.04242.0
56A187.1378.4255.013959.0
67C163.8157.4343.06533.0
78A183.8075.4248.019779.0
89B179.6771.7065.08608.0
910C186.0877.4765.012433.0
1011B163.4157.07NaN6495.0
1112A202.5692.30NaNNaN
1213C177.3791.8079.0NaN
1314B175.9968.39NaN13130.0
1415C199.1189.20NaNNaN
1516A165.6891.8046.013683.0
1617B166.4859.8331.017673.0
1718C191.6282.46NaN12447.0
1819A172.8365.5523.013768.0
1920B156.9951.2962.03054.0
2021C200.2290.2041.0NaN
2122A154.6349.1735.014559.0
2223B157.8752.0867.07398.0
2324A165.5591.8066.019890.0
2425C181.7873.6063.011383.0
2526A164.4357.9934.019899.0
2627B158.2891.8051.0NaN
2728C172.3965.1543.010362.0
2829B162.1255.91NaN13362.0
2930A183.7375.3658.08270.0
3031C181.1972.4241.012616.0
3132B167.2860.5564.018317.0
3233C181.0172.42NaN13021.0
3334A196.6787.00NaNNaN
3435B170.1263.1177.07398.0
3536C180.4772.4278.09554.0
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值