pandas中DataFrame各种方法总结(持续更新)

本文详细介绍了Pandas库的使用,包括DataFrame的创建、基本操作、数据读写、高级索引、数据运算、数据合并等功能。重点讲解了loc和iloc的区别以及数据筛选、自定义运算、数据合并(concat和merge)的方法。此外,还讨论了如何处理SettingWithCopyWarning警告,强调了避免链式赋值的重要性。
摘要由CSDN通过智能技术生成

pandas 最有趣的地方在于里面隐藏了很多包。它是一个核心包,里面有很多其他包的功能。这点很棒,因为你只需要使用 pandas 就可以完成工作。pandas 相当于 python 中 excel:它使用表(也就是 dataframe),能在数据上做各种变换,但还有其他很多功能。

DataFrame的创建

操作代码实现返回值说明
通过ndarray构建DataFramepd.DataFrame(array)
pd.DataFrame(np.random.randn(3,4), columns = [‘a’, ‘b’, ‘c’])
新DataFrame通过Numpy的ndarray构建,
自动生成行列索引,
columns 可指定列索引名
通过dict构建DataFramepd.DataFrame(dict)
dict = {‘A’: 1,
‘B’: pd.Timestamp(‘20190616’),
‘C’:pd.Series(1,index=list(range(4)),dtype=‘float32’),
‘D’: np.array([3] * 4,dtype=‘int32’),
‘E’: [“Python”,“Java”,“C++”,“C”],
‘F’: ‘tiger’ }
新DataFramedict的key为列标签
value为元素
自动生成行索引

DataFrame的相关操作

DataFrame的基本属性和方法

读数据

常用读取文件函数 read_csv, read_excel,read_clipboard, read_sql
如:data = pd.read_csv( my_file.csv , sep= ; , encoding= latin-1 , nrows=1000, skiprows=[2,5])
注:sep 代表的是分隔符。如果你在使用法语数据,excel 中 csv 分隔符是「;」,因此你需要显式地指定它。编码设置为 latin-1 来读取法语字符。nrows=1000 表示读取前 1000 行数据。skiprows=[2,5] 表示你在读取文件的时候会移除第 2 行和第 5 行。

写数据

data.to_csv( my_new_file.csv , index=None)
注:index=None 表示将会以数据本来的样子写入。如果没有写 index=None,你会多出一个第一列,内容是 1,2,3,…,一直到最后一行。
其他的写入函数.to_excel, .to_json, .to_pickle

检查数据

Gives (#rows, #columns) 给出行数和列数
data.describe() 计算基本的统计数据

查看数据

从头查看数据 head()

data.head()  默认返回5行  返回值为DataFrame
head( n ) 方法用于读取前面的 n 行,如果不填参数 n ,默认返回 5 行

从尾查看数据 tail ( )

data.tail()  默认返回5行 返回值为DataFrame
tail( n ) 方法用于读取尾部的 n 行,如果不填参数 n ,默认返回 5 行,空行各个字段的值返回 NaN。

数据形状 shape

data.shape  获取数据形状  返回值为元组
假设data为10行8列的数据 则返回(10,8)
扩展:在机器学习与深度学习模型中,需要将数据集划分为训练集和测试集会造成索引的混乱
可以通过shape方法让索引重新有序
如: data.index = range(data.shape[0])
也可以使用data.reset_index(drop=True)

转置 T

data.T   进行数据转置  返回值为DataFrame 不改变原来的DataFrame
假设data为10行8列的数据 则返回8行10列的数据

设置index(整体全部修改)

data.index = list  整体全部修改index  返回值为DataFrame 不改变原来的DataFrame
说明:按照列表list的数据内容修改index,必须整体全部修改
错误示例:data.index[3] = ‘学生_3’

重新设新的下标索引

data.reset_index(drop=True)  重新设新的下标索引  返回值为DataFrame 不改变原来的DataFrame
说明:drop:默认为False,不删除原来索引,如果为True,删除原来的索引值
一般适用于索引发生混乱的时候,给索引重新从0编号

把某列值设置为新的索引

data.set_index(keys, drop=True)   把某列值设置为新的索引  返回值为DataFrame 不改变原来的DataFrame
说明:keys : 列索引名成或者列索引名称的列表     drop: 默认为False,不删除原来索引,如果为True,删除原来的索引值

获取 DataFrame 的简要摘要

data.info()   返回DataFrame的一些基本信息

DataFrame的基本数据操作

操作代码实现返回值说明
删除若干列df.drop([“a”,“b”,“c”], axis=1)新DataFrame不改变原来的DataFrame
删除列数据del(df[‘G’])None改变原来的DataFrame
增加列数据df[‘G’]=listDataFrame改变原来的DataFrame,list的长度必须的保持一致
对某一列重新赋值df[‘G’]=100DataFrame改变原来的DataFrame
对值排序df.sort_values(by=“open”, ascending=False)
df.sort_values(by=[‘open’, ‘high’])
DataFrame改变原来的DataFrame
by:指定排序参考的键,单个键或者多个键进行排序
ascending:默认True升序,False降序
对某一列重新赋值df[‘G’]=100DataFrame改变原来的DataFrame
对索引排序df.sort_index()DataFrame改变原来的DataFrame
ascending:默认True升序,False降序

DataFrame的高级索引loc、iloc

loc函数:通过行索引 “Index” 中的具体值来取行数据(如取"Index"为"A"的行)
iloc函数:通过行号来取行数据(如取第二行的数据)
本章给出loc、iloc常见的五种用法,并附上详细代码。

1. 利用loc、iloc提取行数据
import numpy as np
import pandas as pd
#创建一个Dataframe
data=pd.DataFrame(np.arange(16).reshape(4,4),index=list('abcd'),columns=list('ABCD'))
 
In[1]: data
Out[1]: 
    A   B   C   D
a   0   1   2   3
b   4   5   6   7
c   8   9  10  11
d  12  13  14  15
 
#取索引为'a'的行
In[2]: data.loc['a']
Out[2]:
A    0
B    1
C    2
D    3
 
#取第一行数据,索引为'a'的行就是第一行,所以结果相同
In[3]: data.iloc[0]
Out[3]:
A    0
B    1
C    2
D    3
2. 利用loc、iloc提取列数据
In[4]:data.loc[:,['A']] #取'A'列所有行,跨列取格式为 data.loc[:,['A','C']]意为取A列和C列的所有行
Out[4]: 
    A
a   0
b   4
c   8
d  12
In[5]:data.iloc[:,'A':'C'] #取连续的列可以用切片,取A~C所有行,注意是左闭右闭
Out[5]: 
    A	B	C
a	0	1	2
b	4	5	6
c	8	9	10
d	12	13	14

In[6]:data.iloc[:,[0]] #取第0列所有行,跨列取格式为 data.iloc[:,[0,2]]意为取第0列和第2列的所有行
Out[6]: 
    A
a   0
b   4
c   8
d  12
In[7]:data.iloc[:,0:2] #取连续的列可以用切片,取0~1的所有行,注意是左闭右开
Out[7]: 
    A	B
a	0	1
b	4	5
c	8	9
d	12	13
3.利用loc、iloc提取指定行、指定列数据
In[8]:data.loc[['a','b'],['A','B']] #提取index为'a','b',列名为'A','B'中的数据
Out[8]: 
   A  B
a  0  1
b  4  5

In[9]:data.loc['b':'d','A':'C'] #提取连续数据index为'b'-'d',列名为'A'-'C'中的数据 切片格式左闭右闭
Out[9]: 
    A	B	C
b	4	5	6
c	8	9	10
d	12	13	14

In[9]:data.iloc[[0,1],[0,1]] #提取第0、1行,第0、1列中的数据
Out[9]: 
   A  B
a  0  1
b  4  5

In[10]:data.iloc[1:4,0:3] #提取第1-3行,第0-2列中的数据 切片格式左闭右开
Out[10]: 
    A	B	C
b	4	5	6
c	8	9	10
d	12	13	14

4.利用loc、iloc提取所有数据
In[11]:data.loc[:,:] #取A,B,C,D列的所有行
Out[11]: 
    A   B   C   D
a   0   1   2   3
b   4   5   6   7
c   8   9  10  11
d  12  13  14  15
 
In[12]:data.iloc[:,:] #取第0,1,2,3列的所有行
Out[12]: 
    A   B   C   D
a   0   1   2   3
b   4   5   6   7
c   8   9  10  11
d  12  13  14  15
5.利用loc函数,根据某个数据来提取数据所在的行
In[13]: data.loc[data['A']==0] #提取data数据(筛选条件: A列中数字为0所在的行数据)
Out[13]: 
   A  B  C  D
a  0  1  2  3
 
In[14]: data.loc[(data['A']==0)&(data['B']==2)] #提取data数据(多个筛选条件)
Out[14]: 
   A  B  C  D
a  0  1  2  3
同时,以下几种写法也可提取数据所在的行,与第五种用法类似,仅作补充。

In[15]: data[data['A']==0] #dataframe用法
In[16]: data[data['A'].isin([0])] #isin函数
In[17]: data[(data['A']==0)&(data['B']==2)] #dataframe用法
In[18]: data[(data['A'].isin([0]))&(data['B'].isin([2]))] #isin函数
 
Out[15]: 
   A  B  C  D

DataFrame的运算

a. 运算函数

操作代码实现返回值说明
算术运算df[‘open’].add(100)
df[‘open’].sub(100)
新Series不改变原来的DataFrame,实际上是Series运算
add(100)是该列每一行的元素都+100
sub(100)是该列每一列的元素都-100
逻辑运算df[“open”] > 100新Series(bool类型)不改变原来的DataFrame,返回值是True与Flase的Serise
筛选df[df[“open”] > 23]
df[(df[“open”] > 23) & (df[“open”] < 24)]
新DataFrame逻辑判断的结果可以作为筛选的依据
筛选函数query()df.query(“open<24 & open>23”)新DataFrame筛选出符合条件的所有数据
筛选函数isin()df[df[“open”].isin([23.53, 23.85])]新DataFrame筛选出"open"列中值为23.53和23.85的所有数据

b.统计运算函数

有时候我们获取到数据之后,想要查看下数据的简单统计指标(最大值、最小值、平均值、中位数等),比如想要查看年龄的最大值,如何实现呢?直接对 age 这一列调用 max方法即可。

user_info.age.max()

类似的,通过调用 minmeanquantilesum 方法可以实现最小值、平均值、中位数以及求和

累加求和 cumsum ( )

来介绍个有意思的方法:cumsum,看名字就发现它和 sum 方法有关系,事实上确实如此,cumsum 也是用来求和的,不过它是用来累加求和的,也就是说它得到的结果与原始的 DataFrame 大小相同。cummax 最后的结果就是将上一次求和的结果与原始当前值求和作为当前值。cumsum 也可以用来操作字符串类型的对象。

一次性获取多个统计指标 describe( )

data.describe()
返回结果如图
在这里插入图片描述
如果想要查看非数字类型的列的统计指标,可以设置 include=["object"] 来获得。
count:总数
unique:去重后的个数
top:出现频率最高的数
freq:出现的最高频率次数

user_info.describe(include=["object"])

在这里插入图片描述

统计下某列中每个值出现的次数 value_counts( )

调用 value_counts方法快速获取 DataFrame 中每个值出现的次数。

user_info.sex.value_counts()
获取某列最大值或最小值对应的索引 idxmax( ) /idxmin()

可以使用idxmaxidxmin 方法完成

user_info.age.idxmax()

在这里插入图片描述

c.自定义运算

  • apply(func, axis=0)
    func:自定义函数;默认是列axis=0,对行进行运算axis=1。
    示例:对’open’, 'close’两列进行自定义运算
>>>data[['open', 'close']].apply(lambda x: x.max() - x.min(), axis=0)   # 返回Series
===运行结果:======================================
open     22.74
close    22.85
dtype: float64

d.逻辑运算

data[data[ column_1 ]== french ]
data[(data[ column_1 ]== french ) & (data[ year_born ]1990)]
data[(data[ column_1 ]
french ) & (data[ year_born ]1990) & ~(data[ city ] London )]
通过逻辑运算来取数据子集。要使用 & (AND)、 ~ (NOT) 和 | (OR),必须在逻辑运算前后加上「and」。
data[data[ column_1 ].isin([ french , english ])]
除了可以在同一列使用多个 OR,你还可以使用.isin() 函数。

apply(),applymap(),map()函数

在Python中如果想要对数据使用函数,可以借助apply(),applymap(),map() 来应用函数,括号里面可以是直接函数式,或者自定义函数(def)或者匿名函数(lambad)

import pandas as pd
import numpy as np
from pandas import DataFrame
from pandas import Series
df1= DataFrame({
                "sales1":[-1,2,3],
                "sales2":[3,-5,7],
               })
df1
#结果
sales1	sales2
0	-1	3
1	2	-5
2	3	7

1、当我们要对数据框(DataFrame)的数据进行按行或按列操作时用apply()

df1.apply(lambda x :x.max()-x.min(),axis=1)
#axis=1,表示跨列对数据进行操作 表格是3*2 axis=1 去掉维度2 得到维度3
#从下面的结果可以看出,我们使用了apply函数之后,系统自动按列寻找每一行的最大值和最小值计算,每一行输出一个值
#结果
0    4
1    7
2    4
dtype: int64
df1.apply(lambda x :x.max()-x.min(),axis=0)
#默认参数axis=0,表示跨行对数据进行操作 表格是3*2 axis=1 去掉维度3 得到维度2
#从下面的结果可以看出,我们使用了apply函数之后,系统自动按行寻找每一列的最大值和最小值计算,每一列输出一个值
#结果
sales1     4
sales2    12
dtype: int64

关于axis参数的理解,请见我另一篇博客
2、当我们要对数据框(DataFrame)的每一个数据进行操作时用applymap(),返回结果是DataFrame格式

df1.applymap(lambda x : 1 if x>0 else 0)
#从下面的结果可以看出,我们使用了applymap函数之后,
#系统自动对每一个数据进行判断,判断之后输出结果
#结果
sales1	sales2
0	0	1
1	1	0
2	1	1

3、当我们要对Series的每一个数据进行操作时用map()

df1["sales1"].map(lambda x : 1 if x>0 else 0)
#df1.sales1就是一个Series
#结果
0    0
1    1
2    1
Name: sales1, dtype: int64

补充:在处理大规模数据集时,pandas 会花费一些时间来进行.map()、.apply()、.applymap() 等操作。tqdm 是一个可以用来帮助预测这些操作的执行何时完成的包(是的,我说谎了,我之前说我们只会使用到 pandas)。

from tqdm import tqdm_notebook
tqdm_notebook().pandas()

用 pandas 设置 tqdm

data[ column_1 ].progress_map(lambda x: x.count( e ))

用 .progress_map() 代替.map()、.apply() 和.applymap() 也是类似的。在 Jupyter 中使用 tqdm 和 pandas 得到的进度条
在这里插入图片描述
tqdm会有另外的专题详细介绍,还没更新。

数据合并(concat,merge)

数据如下:

left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
                     'key2': ['K0', 'K1', 'K0', 'K1'],
                     'A': ['A0', 'A1', 'A2', 'A3'],
                     'B': ['B0', 'B1', 'B2', 'B3']})

right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
                      'key2': ['K0', 'K0', 'K0', 'K0'],
                      'C': ['C0', 'C1', 'C2', 'C3'],
                      'D': ['D0', 'D1', 'D2', 'D3']})

pd.concat实现数据合并

pd.concat([data1, data2], axis=1)
axis=0 跨行操作,行变列不变
axis=1 跨列操作,列变行不变

pd.concat([left,right],axis=1)
# 结果
   key1	key2 A	B  key1 key2 C	 D
0	K0	K0	A0	B0	K0	K0	C0	D0
1	K0	K1	A1	B1	K1	K0	C1	D1
2	K1	K0	A2	B2	K1	K0	C2	D2
3	K2	K1	A3	B3	K2	K0	C3	D3

pd.concat([left,right],axis=0)
# 结果
   key1	key2 A	 B	 C	 D
0	K0	K0	A0	B0	NaN	NaN
1	K0	K1	A1	B1	NaN	NaN
2	K1	K0	A2	B2	NaN	NaN
3	K2	K1	A3	B3	NaN	NaN
0	K0	K0	NaN	NaN	C0	D0
1	K1	K0	NaN	NaN	C1	D1
2	K1	K0	NaN	NaN	C2	D2
3	K2	K0	NaN	NaN	C3	D3

在这里插入图片描述

pd.merge实现数据合并

pd.merge(left, right, how='inner', on=None)
可以指定按照两组数据的共同键值对合并或者左右各自
left: DataFrame
right: 另一个DataFrame
on: 指定的共同键
how:按照什么方式连接

a.内连接

查询两个表中符合条件的共有记录
如图:
在这里插入图片描述
在这里插入图片描述

b.外连接

两个表中所有记录都保留;两个表不存在的数据,使用np.NaN值填充。
在这里插入图片描述

c.左连接

以左表为主,根据条件查询右表数据;左表数据全部保留,右表不存在的数据,使用np.NaN值填充。

在这里插入图片描述
在这里插入图片描述

d.右连接

以右表为主,根据条件查询左表数据;右表数据全部保留,左表不存在的数据,使用np.NaN值填充
在这里插入图片描述
在这里插入图片描述

分组和聚合

DataFrame.groupby(key, as_index=False)key:分组的列数据,可以多个
案例:不同颜色的不同笔的价格数据
进行分组,对颜色分组,对价格进行聚合

>>>col =pd.DataFrame({'color': ['white','red','green','red','green'], 
				      'object': ['pen','pencil','pencil','ashtray','pen'],
				      'price1':[5.56,4.20,1.30,0.56,2.75],
				      'price2':[4.75,4.12,1.60,0.75,3.15]})

	 color    object    price1    price2
0    white    pen       5.56    4.75
1    red      pencil    4.20    4.12
2    green    pencil    1.30    1.60
3    red      ashtray   0.56    0.75
4    green    pen       2.75    3.15

颜色分组 价格聚合

>>>col.groupby(['color'])['price1'].mean()

color
green    2.025
red      2.380
white    5.560
Name: price1, dtype: float64


>>>col['price1'].groupby(col['color']).mean()

color
green    2.025
red      2.380
white    5.560
Name: price1, dtype: float64

添加参数as_index=False后,注意数据的结构的变化

>>>col.groupby(['color'], as_index=False)['price1'].mean()

	 color    price1
0    green    2.025
1    red      2.380
2    white    5.560

agg()---- aggregation聚合函数 (没怎么用过

dataset.groupby('color').agg([list])

交叉表与透视表(没怎么用过)

交叉表:用于计算一列数据对于另外一列数据的分组个数(用于统计分组频率的特殊透视表)

pd.crosstab(df["A"], df["B"])

透视表:透视表是将原有的DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数

dataframe.pivot_table([], index=[])

实操中遇到的问题及其解决办法

统计某列无重复的值

dataframe['列名'].unique()

统计指定列不重复的值的数目

方法一 duplicated

方法:
   DataFrame.duplicated(subset = None,keep =‘first’ )返回boolean数组 一个bool值代表一行
参数:
   subset:用来指定特定的列,默认所有列
 
   keep:{‘first’,‘last’,False},默认’first’
   first:标记重复,True除了第一次出现。
   last:标记重复,True除了最后一次出现。
   False:将所有重复项标记为True。

在这里插入图片描述

import pandas as pd
if __name__=="__main__":
    path = "./test.csv"
    # path_other = "./test_.csv"
    df = pd.read_csv(path, header=0, names=["DEVICE_ID","LNG", "LAT","TEN_GROUP","WEEKDAY","FLOW"])
    # df.to_csv(path, mode="a", index=False, header=False)
    print("DEVICE_ID列不同值数目:\n%s\n\n" % str(len(df['DEVICE_ID'].unique())))
    #keep=False->重复的均置Ture
    t=df.duplicated(subset=["DEVICE_ID"],keep=False)
    print(t)
    #False的个数即代表不重复的键的个数
    print(len(t[t==False])) 
    #选取不重复的键
    print("不重复键:")
    print(df[~t])
#运行结果
DEVICE_ID列不同值数目:3
0      True
1      True
2      True
3      True
4      True
5      True
6      True
7      True
8      True
9      True
10     True
11     True
12     True
13    False
dtype: bool
1
不重复键:
    DEVICE_ID    LNG   LAT  TEN_GROUP  WEEKDAY FLOW
13          3  123.0  43.0        102        1   29

方法二 value_counts()

df["DEVICE_ID"].value_counts()

遍历dataframe的每一行方法比较总结

数据初始化

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(10, size=(1000000, 1)), columns=['num'])

下标遍历

(不建议使用)

for i in range(len(df)):
    if df.iloc[i]['num'] < 5:
        df.loc[i , 'num'] = 15

iterrows遍历

原理是将Dataframe迭代为Series,再返回结果。这一过程中需要进行类型检查,所以,会花费很长的时间。(不建议使用)

for index, row in df.iterrows():
    if row['num'] < 5:
        df.loc[index , 'num'] = 15

itertuples()

原理是将Dataframe迭代为tuple,再进行返回,由于元组不可变的特性,此过程不需要进行类型检查。(效率高,推荐使用)

for row in student.itertuples():
    # print(row)
    print(row.Index, row.name, row.account, row.pwd)
    print(row.Index, getattr(row,'name'), getattr(row,'account'), getattr(row,'pwd'))

for + zip

这种方法是直接手动构造原生tuple,无需关心index数据。(效率高,推荐使用)

for A, B in zip(df['A'], df['B']):
    print(A, B)

SettingWithCopyWarning警告

这段时间一直在用pandas,今天运行前人代码发现报了一个warning:

SettingWithCopyWarning: A value is trying to be set on a copy of a
slice from a DataFrame See the caveats in the documentation:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

SettingWithCopyWarning出现的原因

链式赋值/Chained Assignment

SettingWithCopyWarning会在什么时候出现呢,简而言之就是在链式赋值的时候出现。
以下例子数据以此为例:

df1 = pd.DataFrame(np.random.random(20).reshape((10,2)), columns=list('AB'))
df1

在这里插入图片描述

什么是链式

链式就是进行多次同类型的操作,比如a = b = c = 4就是一个链式操作。在这里的链式操作主要是指,对于一个pandas格式的表,选取两次或者以上次数的其中结果。
比如选取其中A值小于0.3的行得到:

df1[df1.A < 0.3]

那么选取其中所有A<0.3的B列值可以写为:

df1[df1.A < 0.3].B

以上中,先选取左右A<0.3的行,其次再从中选取B列,上述操作将其分为两部,那么这样就是链式操作。

那么链式赋值呢?

如果此时要进行:选取其中所有A<0.3的B列值并将其赋值为1,如果进行:

df1[df1.A < 0.3].B = 1

此时就会报错SettingWithCopyWarning的Warning
如果此时再查看df1里面的值,会发现完全没有改变。
【所以此时这个爆warning是非常有意义的,如果单纯的忽略掉则会导致程序错误。】
根据会提示用loc函数。
用loc函数如下:

df1.loc[df1.A<0.3, 'B'] = 1

运行完后再查看就会发现df1里面的对应着都变为1了。

出现的原因

官方的解释是,pandas这个机制设计如此,凡事出现链式赋值的情况,pandas都是不能够确定到底返回的是一个引用还是一个拷贝。所以遇到这种情况就干脆报warning

更隐蔽的链式赋值

有些时候比如将链式给拆解成为多步的时候,就是一些隐式的情况。
比如:

df2 = df1.loc[df1.A<0.3]
df2.loc[1,'B'] = 2

虽然这两步每步都用了loc,但是凡是把取值(GET)操作分为两步的,仍然是链式赋值的状态,所以仍然会报warning。
不过再次查看df2发现df2的值确实已经改变过来了,查看df1的值,发现df1的值没有变。
所以之前那次用loc取出的就是引用,这次就变成拷贝了。也就是说链式赋值是一个要避免的状态。
如果明确说要用拷贝怎么办,就是如下:

df2 = df1.loc[df1.A<0.3].copy()

总结

这里总结一下pandas的这个问题:

  • 避免任何形式的链式赋值,有可能会报warning也有可能不会报。而且即使报了,可能有问题,也可能没问题。
  • 如果需要用到多级选取,则用loc
  • 如果需要用到拷贝,则直接加copy()函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值