《利用Python 进行数据分析》 - 笔记(3)
(2)values 属性也会以二维ndarray 的形式返回DataFrame 中的数据
发布日期:2021-06-30 19:50:04
浏览次数:3
分类:技术文章
本文共 36277 字,大约阅读时间需要 120 分钟。
问题导读:
1.pandas的数据结构介绍
2.利用pandas对数据的基本操作
3.汇总和计算描述统计方法
4.处理缺失数据
5.层次化索引
解决方案:
pandas的数据结构介绍:
(1)Series
- Series 是一种类似于一维数组的对象,它由一组数据(各种Numpy数据类型)以及与之相关的数据标签(索引)组成
In [6]: obj = pd.Series([1,2,3,4])In [7]: objOut[7]: 0 11 22 33 4dtype: int64
- Series 字符串的表现形式为:索引在左边,值在右边
In [8]: obj.valuesOut[8]: array([1, 2, 3, 4])In [9]: obj.indexOut[9]: Int64Index([0, 1, 2, 3], dtype='int64')
- 创建的Series 带有一个可以对各个数据点进行标记的索引
In [10]: obj2 = pd.Series([2,4,1,6],index=['a','b','c','d'])In [11]: obj2Out[11]: a 2b 4c 1d 6dtype: int64In [12]: obj2.cOut[12]: 1
- 计算(根据bool型数据过滤、标量乘法、应用数学函数)之后index 和 values 依然保持连接
In [18]: obj2[obj2 > 0]Out[18]: a 2b 4c 1d 6dtype: int64In [19]: obj2 * 2Out[19]: a 4b 8c 2d 12dtype: int64In [20]: np.exp(obj2)Out[20]: a 7.389056b 54.598150c 2.718282d 403.428793dtype: float64
- 通过python字典直接创建Series
In [21]: sdata = {'Ohio':2000, 'Texas':3000, 'Utah':3425, 'Oregon':3908}In [22]: obj3 = pd.Series(sdata)In [23]: obj3Out[23]: Ohio 2000Oregon 3908Texas 3000Utah 3425dtype: int64In [24]: obj3.valuesOut[24]: array([2000, 3908, 3000, 3425])In [25]: obj3.indexOut[25]: Index([u'Ohio', u'Oregon', u'Texas', u'Utah'], dtype='object')
- 如果只传入一个字典,则结果中的索引就是按照原字典的键(有序排列)
- 如果传入的index 列表中的元素和字典中的键相互匹配不到,则该索引位置的values 为NaN
n [26]: states = ['california','Ohio','Oregon','Texas']In [27]: obj4 = pd.Series(sdata,index = states)In [28]: obj4Out[28]: california NaNOhio 2000Oregon 3908Texas 3000dtype: float64
- pandas 的isnull 和notnull 函数可以用于检测缺失数据
In [34]: obj4.isnull()Out[34]: california TrueOhio FalseOregon FalseTexas Falsedtype: boolIn [35]: obj4.notnull()Out[35]: california FalseOhio TrueOregon TrueTexas Truedtype: bool
- Series 一个重要的功能是:它在运算中会自动对齐不同索引的数据
In [36]: obj3Out[36]: Ohio 2000Oregon 3908Texas 3000Utah 3425dtype: int64In [37]: obj4Out[37]: california NaNOhio 2000Oregon 3908Texas 3000dtype: float64In [38]: obj3 + obj4Out[38]: Ohio 4000Oregon 7816Texas 6000Utah NaNcalifornia NaNdtype: float64
- Series 对象本身 及其索引都有一个name 属性
- Series 的索引可以通过赋值的方式就地修改
In [40]: obj4.name = 'population'In [41]: obj4.index.name = 'state'In [42]: obj4Out[42]: statecalifornia NaNOhio 2000Oregon 3908Texas 3000Name: population, dtype: float64In [43]: objOut[43]: 0 11 22 33 4dtype: int64In [45]: obj.index = ['a','b','c','d']In [46]: objOut[46]: a 1b 2c 3d 4dtype: int64
(2)DataFrame
- DataFrame 是一个表格型的数据结构,每列可以是不同的值类型(数值,字符串,布尔值)。
- DataFrame 可以被看做由Series组成的字典(共用同一个索引)
- 通过字典创建DataFrame:每一columns对应的是字典中每个key - value 对,有index 行
In [16]: data = {'state':['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],'year':[2000, 2001, 2002, 2003, 2004],'pop':[1.5, 1.7, 3.6, 2.4, 2.9]}In [17]: dataOut[17]: {'pop': [1.5, 1.7, 3.6, 2.4, 2.9], 'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 'year': [2000, 2001, 2002, 2003, 2004]}In [18]: frame01 = pd.DataFrame(data,columns = ['year','state','pop'],index = ['1','2','3','4','5'])In [19]: frame01Out[19]: year state pop1 2000 Ohio 1.52 2001 Ohio 1.73 2002 Ohio 3.64 2003 Nevada 2.45 2004 Nevada 2.9
- 如何指定了列序列,则DataFrame的列就会按照制定顺序进行排序
- 和Series 一样,如果传入的列在数据中找不到,就会产生NA值
- 获取列,获得的是一个series
In [31]: frame01['year']Out[31]: 1 20002 20013 20024 20035 2004Name: year, dtype: int64In [32]: frame01['pop']Out[32]: 1 1.52 1.73 3.64 2.45 2.9Name: pop, dtype: float64In [33]: frame01.stateOut[33]: 1 Ohio2 Ohio3 Ohio4 Nevada5 NevadaName: state, dtype: object
- 行可以通过索引字段ix获取
In [5]: frame01.ix[1]Out[5]: year 2001state Ohiopop 1.7Name: 2, dtype: objectIn [6]: frame01.ix['1']Out[6]: year 2000state Ohiopop 1.5Name: 1, dtype: object
- 列的索引依然为DataFrame 的索引
In [35]: frame02Out[35]: state year popone Ohio 2000 1.5two Ohio 2001 1.7three Ohio 2002 3.6four Nevada 2003 2.4five Nevada 2004 2.9In [36]: frame02.stateOut[36]: one Ohiotwo Ohiothree Ohiofour Nevadafive NevadaName: state, dtype: objectIn [37]: frame02.yearOut[37]: one 2000two 2001three 2002four 2003five 2004Name: year, dtype: int64
- 修改元素
- 列可以通过赋值的方式进行修改
- 将列表或数组赋值给某个列时,其长度必须和DataFrame的长度相匹配
- 如果赋值的是一个Series,就会精确匹配DataFrame的索引,所有的空位都将被填上缺失值
In [22]: frameOut[22]: state year popone Ohio 1 1two Ohio 1 1three Ohio 1 1four Nevada 1 1five Nevada 1 1In [23]: frame.year = np.arange(2011,2016)In [24]: frame.pop = np.random.randn(5)In [25]: frameOut[25]: state year popone Ohio 2011 0.968678two Ohio 2012 0.280024three Ohio 2013 -0.396301four Nevada 2014 -0.132369five Nevada 2015 -0.181226In [40]: frameOut[40]: state year pop debtone Ohio 1 1 NaNtwo Ohio 1 1 NaNthree Ohio 1 1 NaNfour Nevada 1 1 NaNfive Nevada 1 1 NaNIn [41]: val = pd.Series([-1.2,-1.5,-1.7], index = ['two', 'four', 'five'])In [42]: frame['dedt'] = valIn [43]: frameOut[43]: state year pop debt dedtone Ohio 1 1 NaN NaNtwo Ohio 1 1 NaN -1.2three Ohio 1 1 NaN NaNfour Nevada 1 1 NaN -1.5five Nevada 1 1 NaN -1.7
- 删除列
In [44]: frame['newline'] = frame.state != 'Ohio'In [45]: frameOut[45]: state year pop debt dedt newlineone Ohio 1 1 NaN NaN Falsetwo Ohio 1 1 NaN -1.2 Falsethree Ohio 1 1 NaN NaN Falsefour Nevada 1 1 NaN -1.5 Truefive Nevada 1 1 NaN -1.7 TrueIn [46]: del frame['newline']In [47]: frameOut[47]: state year pop debt dedtone Ohio 1 1 NaN NaNtwo Ohio 1 1 NaN -1.2three Ohio 1 1 NaN NaNfour Nevada 1 1 NaN -1.5five Nevada 1 1 NaN -1.7
- 补充说明
In [69]: frame.columns.name = 'state'In [70]: frame.index.name = 'myname'In [71]: frame.columns.name = 'state'In [72]: frameOut[72]: state state year pop debt dedtmyname one Ohio 1 1 NaN NaNtwo Ohio 1 1 NaN -1.2three Ohio 1 1 NaN NaNfour Nevada 1 1 NaN -1.5five Nevada 1 1 NaN -1.7
In [73]: frame.valuesOut[73]: array([['Ohio', '1', '1', nan, nan], ['Ohio', '1', '1', nan, -1.2], ['Ohio', '1', '1', nan, nan], ['Nevada', '1', '1', nan, -1.5], ['Nevada', '1', '1', nan, -1.7]], dtype=object)(3)可以输入给DataFrame构造器的数据
(3)索引对象
- pandas 的索引对象负责管理轴标签和其他元数据(比如轴名称)
n [4]: obj = pd.Series(range(3),index=['a','b','c'])In [5]: objOut[5]: a 0b 1c 2dtype: int64In [6]: index = obj.indexIn [7]: indexOut[7]: Index([u'a', u'b', u'c'], dtype='object')In [8]: index[1:]Out[8]: Index([u'b', u'c'], dtype='object')In [9]: index[
- Index 对象是不可以修改的
- 不可修改性很重要,因为这样才能使Index对象在多个数据结构之间安全共享
n [4]: obj = pd.Series(range(3),index=['a','b','c'])In [5]: objOut[5]: a 0b 1c 2dtype: int64In [6]: index = obj.indexIn [7]: indexOut[7]: Index([u'a', u'b', u'c'], dtype='object')In [8]: index[1:]Out[8]: Index([u'b', u'c'], dtype='object')
In [42]: indexOut[42]: Index([u'a', u'b', u'c'], dtype='object')In [43]: obj2 = pd.Series(range(3),index = index)In [44]: obj2.indexobj2.indexIn [44]: obj2.index is indexOut[44]: TrueIn [45]: indexOut[45]: Index([u'a', u'b', u'c'], dtype='object')In [46]: obj2 = pd.Series(range(3),index = index)In [47]: obj2.index is indexOut[47]: True
- Python中的对象包含三要素:id、type、value
In [48]: index2=indexIn [49]: index2Out[49]: Index([u'a', u'b', u'c'], dtype='object')In [50]: obj2.index is index2Out[50]: TrueIn [51]: index3 = ['a','b','c']In [52]: index3 is indexOut[52]: FalseIn [53]: obj2.index is index3Out[53]: False
- pandas中主要的Index对象
- Index的功能也类似一个固定大小的集合
In [28]: frameOut[28]: Nevada Ohio2000 2.2 1.52001 2.1 1.72002 2.1 3.6In [29]: 'Ohio' in frame.columnsOut[29]: TrueIn [30]: 2002 in frame.indexOut[30]: TrueIn [31]: 1999 in frame.indexOut[31]: False
- Index的方法和属性
pandas数据处理基本方法:
(1)重新索引
- pandas对象的一个重要的方法是reindex,其作用是创建一个适应新索引的新对象
- 调用Series 的 reindex 将会根据新索引进行重排,如果某个索引值当前不存在,就引入缺失值
In [38]: obj = pd.Series([4.5,7.2,-5.3,3.8], index = ['d','b','a','c'])In [39]: objOut[39]: d 4.5b 7.2a -5.3c 3.8dtype: float64In [40]: obj2 = obj.reindex(['a','b','c','d','e'])In [41]: obj2Out[41]: a -5.3b 7.2c 3.8d 4.5e NaNdtype: float64
- 为了防止索引值不存在的情况可以用 fill_value 值来设置无索引的默认值
In [42]: obj2 = obj.reindex(['a','b','c','d','e'],fill_value = 0)In [43]: obj2Out[43]: a -5.3b 7.2c 3.8d 4.5e 0.0dtype: float64
- 对于时间序列这样的有序数据,重新索引时可以需要做一些插值操作处理,method选项即可达到此目的
- ffill可以实现向前值填充
In [44]: obj3 = pd.Series(['blue','purple','yellow'],index=[0,2,4])In [45]: obj3.reindex(range(6),method='ffill')Out[45]: 0 blue1 blue2 purple3 purple4 yellow5 yellowdtype: object
- reindex的(插值)method选项
- 对于DataFrame,reindex可以修改(行)索引,列,或两个都修改
- 如果仅仅传入一个序列,则会重新索引行
In [47]: frame = pd.DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'], ....: columns=['Ohio','Texas','California'])In [48]: frameOut[48]: Ohio Texas Californiaa 0 1 2c 3 4 5d 6 7 8In [49]: frame2 = frame.reindex(['a','b','c','d'])In [50]: frame2Out[50]: Ohio Texas Californiaa 0 1 2b NaN NaN NaNc 3 4 5d 6 7 8In [51]: states = ['Texas','Utah','California']In [52]: frame.reindex(columns=states)Out[52]: Texas Utah Californiaa 1 NaN 2c 4 NaN 5d 7 NaN 8
- 对行和列同时进行索引,而插值则只能按行应用(即轴0)
In [54]: frame.reindex(index=['a','b','c','d'],method = 'ffill', ....: columns = states)Out[54]: Texas Utah Californiaa 1 NaN 2b 1 NaN 2c 4 NaN 5d 7 NaN 8
- 利用ix的标签索引功能索引
In [56]: frame.ix[['a','c'],'Texas']Out[56]: a 1c 4Name: Texas, dtype: int64
- reindex函数的参数
(2)丢弃指定轴上的项
- drop方法返回的是一个在指定轴上删除了指定值的新对象
In [58]: obj = pd.Series(np.arange(5.),index=['a','b','c','d','e'])In [59]: new_obj = obj.drop('c')In [60]: objOut[60]: a 0b 1c 2d 3e 4dtype: float64In [61]: new_objOut[61]: a 0b 1d 3e 4dtype: float64
- DataFrame可以删除任意轴上的索引值
In [68]: data = pd.DataFrame(np.arange(16).reshape((4,4)),index=['Ohio','Colorado','Utah','New York'],columns=['one','two','three','four'])In [69]: dataOut[69]: one two three fourOhio 0 1 2 3Colorado 4 5 6 7Utah 8 9 10 11New York 12 13 14 15In [70]: data.drop(['Colorado','Ohio'])Out[70]: one two three fourUtah 8 9 10 11New York 12 13 14 15In [71]: data.drop('two',axis=1)Out[71]: one three fourOhio 0 2 3Colorado 4 6 7Utah 8 10 11New York 12 14 15In [72]: data.drop(['one','four'],axis=1)Out[72]: two threeOhio 1 2Colorado 5 6Utah 9 10New York 13 14
(3)索引、选取和过滤
- Series 索引工作方式类似与numpy数组的索引,只不过Series的索引值不只是整数
In [3]: obj = pd.Series(np.arange(4.),index=['a','b','c','d'])In [4]: objOut[4]: a 0b 1c 2d 3dtype: float64In [5]: obj['b']Out[5]: 1.0In [6]: obj[1]Out[6]: 1.0In [7]: obj[2:4]Out[7]: c 2d 3dtype: float64In [8]: obj[['b','d']]Out[8]: b 1d 3dtype: float64In [9]: obj[['1','3']]Out[9]: 1 NaN3 NaNdtype: float64In [10]: obj[[1,3]]Out[10]: b 1d 3dtype: float64In [11]: obj[obj<2]Out[11]: a 0b 1dtype: float64
- 利用标签的切片运算与普通的python切片运算不同,其末端是包含的,而普通的切片不包含
In [18]: obj[0:3]Out[18]: a 0b 1c 2dtype: float64In [19]: obj['a':'d']Out[19]: a 0b 1c 2d 3dtype: float64
- 切片赋值
In [21]: obj['a':'c'] = 1In [22]: objOut[22]: a 1b 1c 1d 3dtype: float64
- 对DataFrame进行索引就是获取一个或多个列
- 索引方式有几个特殊的情况。首先通过切片或布尔型数组选取行
In [24]: data = pd.DataFrame(np.arange(16).reshape((4,4)),index = ['Ohio','Colorado','Utah','New York'], ....: columns=['one','two','three','four'])In [25]: dataOut[25]: one two three fourOhio 0 1 2 3Colorado 4 5 6 7Utah 8 9 10 11New York 12 13 14 15[4 rows x 4 columns]In [26]: data[:2]Out[26]: one two three fourOhio 0 1 2 3Colorado 4 5 6 7[2 rows x 4 columns]In [27]: data[data['three'] > 5]Out[27]: one two three fourColorado 4 5 6 7Utah 8 9 10 11New York 12 13 14 15[3 rows x 4 columns]
- 上面那种方式比较不符合逻辑,毕竟来源于实践
- 另一种方式可以通过布尔型DataFrame来进行索引
In [38]: data < 5Out[38]: one two three fourOhio True True True TrueColorado True False False FalseUtah False False False FalseNew York False False False False[4 rows x 4 columns]In [39]: data[data < 5] = 0In [40]: dataOut[40]: one two three fourOhio 0 0 0 0Colorado 0 5 6 7Utah 8 9 10 11New York 12 13 14 15[4 rows x 4 columns]
- 使用ix专门的索引字段
In [44]: data.ix['Colorado',['tow','three']]Out[44]: tow NaNthree 6Name: Colorado, dtype: float64In [45]: data.ix['Colorado',['two','three']]Out[45]: two 5three 6Name: Colorado, dtype: int64In [46]: data.ix[['Colorado','Utah'],[3,1,0]]Out[46]: four two oneColorado 7 5 0Utah 11 9 8[2 rows x 3 columns]In [47]: data.ix[2]Out[47]: one 8two 9three 10four 11Name: Utah, dtype: int64In [48]: data.ix[:'Utah','two']Out[48]: Ohio 0Colorado 5Utah 9Name: two, dtype: int64In [49]: data.ix[data.three > 5,:3]Out[49]: one two threeColorado 0 5 6Utah 8 9 10New York 12 13 14[3 rows x 3 columns]
- DataFrame的索引选项:
(4)算数运算和数据对齐
- pandas最重要的一个功能是可以对不同索引值的对象进行算数运算。
- 如果存在不同的索引对,则结果的索引就是该索引对的并集
In [51]: s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index = ['a','c','d','e'])In [52]: s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1], index = ['a','c','e','f','g'])In [53]: s1Out[53]: a 7.3c -2.5d 3.4e 1.5dtype: float64In [54]: s2Out[54]: a -2.1c 3.6e -1.5f 4.0g 3.1dtype: float64In [55]: s1 + s2Out[55]: a 5.2c 1.1d NaNe 0.0f NaNg NaNdtype: float64
- 对于DataFrame,对齐操作会同时发生在行和列上
In [61]: df1 = pd.DataFrame(np.arange(9.).reshape((3,3)),columns=list('bcd'),index = ['Ohio','Texas','Colorado'])In [62]: df2 = pd.DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),index = ['Utah','Ohio','Texas','Oregon'])In [63]: df1Out[63]: b c dOhio 0 1 2Texas 3 4 5Colorado 6 7 8[3 rows x 3 columns]In [64]: df2Out[64]: b d eUtah 0 1 2Ohio 3 4 5Texas 6 7 8Oregon 9 10 11[4 rows x 3 columns]In [65]: df1 + df2Out[65]: b c d eColorado NaN NaN NaN NaNOhio 3 NaN 6 NaNOregon NaN NaN NaN NaNTexas 9 NaN 12 NaNUtah NaN NaN NaN NaN[5 rows x 4 columns]
4.1 在算数方法中填充值
- 在对不同索引对象进行算数运算时,你可能希望当一个对象中某个轴标签在另一个对象中找不到时填充一个特殊值
In [66]: df1 = pd.DataFrame(np.arange(12.).reshape((3,4)),columns=list('abcd'))In [67]: df2 = pd.DataFrame(np.arange(20.).reshape((4,5)),columns=list('abcde')) In [68]: df1 + df2Out[68]: a b c d e0 0 2 4 6 NaN1 9 11 13 15 NaN2 18 20 22 24 NaN3 NaN NaN NaN NaN NaN[4 rows x 5 columns]In [69]: df1.add(df2,fill_value=0)Out[69]: a b c d e0 0 2 4 6 41 9 11 13 15 92 18 20 22 24 143 15 16 17 18 19[4 rows x 5 columns]
- 与此类似,Series 或 DataFrame 重新索引时,也可以指定一个填充值
In [72]: df1.reindex(columns=df2.columns,fill_value=0)Out[72]: a b c d e0 0 1 2 3 01 4 5 6 7 02 8 9 10 11 0[3 rows x 5 columns]
- 算术方法
4.2 DataFrame和Series之间的运算
- 先来计算一个二维数组与其某行之间的差
- 这样的运算叫做广播
In [73]: arr = np.arange(12.).reshape((3,4))In [74]: arrOut[74]: array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]])In [75]: arr[0]Out[75]: array([ 0., 1., 2., 3.])In [76]: array([0.,1.,2.,3.])Out[76]: array([ 0., 1., 2., 3.])In [77]: arr - arr[0]Out[77]: array([[ 0., 0., 0., 0.], [ 4., 4., 4., 4.], [ 8., 8., 8., 8.]])
- DataFrame与Series 之间的运算和上面差不多
- 默认情况下,DataFrame 和 Series 之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着行向下广播
In [78]: frame = pd.DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon'])In [79]: series = frame.ix[0]In [80]: frameOut[80]: b d eUtah 0 1 2Ohio 3 4 5Texas 6 7 8Oregon 9 10 11[4 rows x 3 columns]In [81]: seriesOut[81]: b 0d 1e 2Name: Utah, dtype: float64In [82]: frame - seriesOut[82]: b d eUtah 0 0 0Ohio 3 3 3Texas 6 6 6Oregon 9 9 9[4 rows x 3 columns]
- 如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集
In [89]: series2 = pd.Series(range(3),index=['b','e','f'])In [90]: frame + series2Out[90]: b d e fUtah 0 NaN 3 NaNOhio 3 NaN 6 NaNTexas 6 NaN 9 NaNOregon 9 NaN 12 NaN[4 rows x 4 columns]
- 如果你希望匹配行且在列上广播,则必须使用算术运算方法
In [98]: series3 = frame['d']In [99]: frameOut[99]: b d eUtah 0 1 2Ohio 3 4 5Texas 6 7 8Oregon 9 10 11[4 rows x 3 columns]In [100]: series3Out[100]: Utah 1Ohio 4Texas 7Oregon 10Name: d, dtype: float64In [101]: frame.sub(series3,axis=0)Out[101]: b d eUtah -1 0 1Ohio -1 0 1Texas -1 0 1Oregon -1 0 1[4 rows x 3 columns]
(5)函数应用和映射
- NumPy 的ufuncs(元素级数组方法)也可用于操作pandas对象
- abs() 函数返回数字的绝对值
In [102]: frame = pd.DataFrame(np.random.randn(4,3),columns=list('bde'), .....: index=['Utah','Ohio','Texas','Oregon'])In [103]: frameOut[103]: b d eUtah 0.752307 -1.701850 0.231538Ohio -1.156549 -0.116461 -0.224967Texas -1.919040 0.287937 0.580048Oregon -1.817225 1.545293 -0.606694[4 rows x 3 columns]In [104]: np.abs(frame)Out[104]: b d eUtah 0.752307 1.701850 0.231538Ohio 1.156549 0.116461 0.224967Texas 1.919040 0.287937 0.580048Oregon 1.817225 1.545293 0.606694[4 rows x 3 columns]
- DataFrame的apply 方法 将函数应用到由各列或行所形成的一维数组上
-
lambda只是一个表达式,函数体比def简单很多。
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda表达式是起到一个函数速写的作用。允许在代码内嵌入一个函数的定义。
In [106]: f = lambda x:x.max() - x.min()In [107]: frame.apply(f)Out[107]: b 2.671347d 3.247143e 1.186742dtype: float64In [108]: frame.apply(f,axis=1)Out[108]: Utah 2.454157Ohio 1.040089Texas 2.499088Oregon 3.362518dtype: float64
- 除了标量外,传递给apply的函数还可以返回由多个值组成的Series
In [120]: def f(x): return pd.Series([x.min(),x.max()],index=['min','max']) .....: In [121]: frame.apply(f)Out[121]: b d emin -1.919040 -1.701850 -0.606694max 0.752307 1.545293 0.580048[2 rows x 3 columns]
- 元素级的Python函数也是可以用的
- format 是 得到浮点值的格式化字符串
- 使用applymap函数
In [123]: format = lambda x:'%.2f' % xIn [124]: frame.applymap(format)Out[124]: b d eUtah 0.75 -1.70 0.23Ohio -1.16 -0.12 -0.22Texas -1.92 0.29 0.58Oregon -1.82 1.55 -0.61[4 rows x 3 columns]
- Series有个应用与元素级别的函数的map方法
In [125]: frame['e'].map(format)Out[125]: Utah 0.23Ohio -0.22Texas 0.58Oregon -0.61Name: e, dtype: object
- 要对行或列索引进行排序(按字典顺序),可以使用sort_index方法,它将返回一个已排序的新对象
In [127]: obj = pd.Series(range(4),index = ['b','a','d','c'])In [128]: obj.sort_index()Out[128]: a 1b 0c 3d 2dtype: int64
- 对于DataFrame则可以根据任意一个轴上的索引进行排序
In [132]: frameOut[132]: d a b cthree 0 1 2 3one 4 5 6 7[2 rows x 4 columns]In [133]: frame.sort_index()Out[133]: d a b cone 4 5 6 7three 0 1 2 3[2 rows x 4 columns]In [134]: frame.sort_index(axis=1)Out[134]: a b c dthree 1 2 3 0one 5 6 7 4[2 rows x 4 columns]
- 数据默认是按照升序排序的,但也可以降序排序
In [135]: frame.sort_index(axis=1,ascending=False)Out[135]: d c b athree 0 3 2 1one 4 7 6 5[2 rows x 4 columns]
- 如果按值对Series进行排序,可使用其order方法
In [137]: obj = pd.Series([4,7,-3,2])In [138]: obj.order()Out[138]: 2 -33 20 41 7dtype: int64
- 在排序时,任何缺失值默认都会被放在Series的末尾
In [139]: obj = pd.Series([4,np.nan,7,np.nan,-3,2])In [140]: obj.order()Out[140]: 4 -35 20 42 71 NaN3 NaNdtype: float64
- 在DataFrame 上,你可能希望根据一个或多个列中的值进行排序
- 我们只要将一个或多个列中的名字传递给by选项即可
In [141]: frame = pd.DataFrame({'b':[4,7,-3,2],'a':[0,1,0,1]})In [142]: frameOut[142]: a b0 0 41 1 72 0 -33 1 2[4 rows x 2 columns]In [143]: frame.sort_index(by='b')Out[143]: a b2 0 -33 1 20 0 41 1 7[4 rows x 2 columns]In [144]: frame.sort_index(by=['a','b'])Out[144]: a b2 0 -30 0 43 1 21 1 7[4 rows x 2 columns]
- 排名:与排序关系密切,它会增设一个排名值(从1开始,一直到数组中有效的数据);有时候它会根据某种规则破坏平级关系
- 默认情况下rank是通过‘为各组分配一个平均排名’的方式破坏平级关系
In [153]: obj = pd.Series([7,-5,7,4,2,0,4])In [154]: obj.rank()Out[154]: 0 6.51 1.02 6.53 4.54 3.05 2.06 4.5dtype: float64
- 要根据原数据中顺序给出排名
- 也可以按降序进行排名
- DataFrame 可以在行或列上计算排名(只需要声明axis即可),这里不再示范了
In [155]: obj.rank(method='first')Out[155]: 0 61 12 73 44 35 26 5dtype: float64In [156]: obj.rank(ascending=False,method='max')Out[156]: 0 21 72 23 44 55 66 4dtype: float64
- 排名时用于破坏平级关系的method选项
(6)带有重复值的轴索引
- 许多pandas函数(如reindex)都要求标签唯一,但这并不是强制性
- 索引的is_unique属性可以告诉你它的值是否是唯一
In [157]: obj = pd.Series(range(5),index = ['a','a','b','b','c'])In [158]: objOut[158]: a 0a 1b 2b 3c 4dtype: int64In [159]: obj.index.is_uniqueOut[159]: False
- 对于带有重复值的索引,数据选取的行为将会有些不同
- 某个索引对应多个值,将会返回一个Series
- 而对应单个值,则返回一个标量值
In [161]: obj['a']Out[161]: a 0a 1dtype: int64In [162]: obj['b']Out[162]: b 2b 3dtype: int64
- 对DataFrame 进行索引的时候也是这样
- 对于重复索引将返回一个DataFrame
In [163]: df = pd.DataFrame(np.random.randn(4,3),index=['a','a','b','b'])In [164]: dfOut[164]: 0 1 2a 0.788165 -0.046659 0.781164a -1.329601 0.245623 0.074344b 0.126223 0.141285 -2.280768b 1.605712 -0.450426 -0.083235[4 rows x 3 columns]In [165]: df.ix['b']Out[165]: 0 1 2b 0.126223 0.141285 -2.280768b 1.605712 -0.450426 -0.083235[2 rows x 3 columns]
汇总和计算描述统计:
- pandas对象拥有一组常用的数学和统计方法,他们大部分都属于约简和汇总统计
- 他们都是基于没有缺失数据的假设而构建的
- na值会被自动排除,除非整个切片(整个行或者列)都是na ,通过skipna 选项可以禁用该功能
In [54]: df = pd.DataFrame([[1.4,np.nan],[7.1,-4.5],[np.nan,np.nan],[0.75,-1.3]],index = ['a','b','c','d'], ....: columns=['one','two'])In [55]: dfOut[55]: one twoa 1.40 NaNb 7.10 -4.5c NaN NaNd 0.75 -1.3[4 rows x 2 columns]In [56]: df.sum()Out[56]: one 9.25two -5.80dtype: float64In [57]: df.sum(1)Out[57]: a 1.40b 2.60c NaNd -0.55dtype: float64In [58]: df.mean(axis=1,skipna=False)Out[58]: a NaNb 1.300c NaNd -0.275dtype: float64
- 约简方法的选项
- 有些方法返回的是间接统计
- idxmin/idxmax
- 有些方法则是累计型的
In [64]: df.idxmax()Out[64]: one btwo ddtype: objectIn [65]: df.cumsum()Out[65]: one twoa 1.40 NaNb 8.50 -4.5c NaN NaNd 9.25 -5.8[4 rows x 2 columns]
- describe 即不是约简型也不是累计型它用于一次性产生多个汇总统计
In [67]: df.describe()Out[67]: one twocount 3.000000 2.000000mean 3.083333 -2.900000std 3.493685 2.262742min 0.750000 -4.50000025% 1.075000 -3.70000050% 1.400000 -2.90000075% 4.250000 -2.100000max 7.100000 -1.300000
- 对于非数组型数据,describe会产生另外一种汇总统计
In [69]: obj = pd.Series(['a','a','b','c']*4)In [70]: objOut[70]: 0 a1 a2 b3 c4 a5 a6 b7 c8 a9 a10 b11 c12 a13 a14 b15 cdtype: objectIn [71]: obj.describe()Out[71]: count 16unique 3top afreq 8dtype: object
- 描述和汇总统计
(1)相关系数与协方差
- 读取来自Yahoo!Finance的股票价格和成交量
#!/usr/bin/env python# coding=utf-8import pandas as pdimport pandas.io.data as weball_data = {}for ticker in ['AAPL','IBM','MSFT','GOOG']: all_data[ticker] = web.get_data_yahoo(ticker,'1/1/2000','1/1/2010')price = pd.DataFrame({tic:data['Adj Close'] for tic,data in all_data.iteritems()})volume = pd.DataFrame({tic:data['Volume'] for tic, data in all_data.iteritems()})
- Series的corr方法用于计算两个Series中重叠的,非NA的,按索引对齐的值的相关系数
- cov用于计算协方差
In [33]: returns = price.pct_change()In [34]: returns.tail()Out[34]: AAPL GOOG IBM MSFTDate 2009-12-24 0.034339 0.011117 0.004385 0.0025872009-12-28 0.012294 0.007098 0.013326 0.0054842009-12-29 -0.011861 -0.005571 -0.003477 0.0070582009-12-30 0.012147 0.005376 0.005461 -0.0136992009-12-31 -0.004300 -0.004416 -0.012597 -0.015504[5 rows x 4 columns]In [35]: returns.MSFT.corr(returns.IBM)Out[35]: 0.49597969625135241In [36]: returns.MSFT.cov(returns.IBM)Out[36]: 0.00021595764700046635
- DataFrame的corr 和 cov 方法将以DataFrame的形式返回完整的相关系数或协方差矩阵
In [38]: returns.corr()Out[38]: AAPL GOOG IBM MSFTAAPL 1.000000 0.470676 0.410011 0.424305GOOG 0.470676 1.000000 0.390689 0.443587IBM 0.410011 0.390689 1.000000 0.495980MSFT 0.424305 0.443587 0.495980 1.000000[4 rows x 4 columns]In [39]: returns.cov()Out[39]: AAPL GOOG IBM MSFTAAPL 0.001027 0.000303 0.000252 0.000309GOOG 0.000303 0.000580 0.000142 0.000205IBM 0.000252 0.000142 0.000367 0.000216MSFT 0.000309 0.000205 0.000216 0.000516[4 rows x 4 columns]
- 利用DataFrame的corrwidth方法,你可以计算其列或行跟另一个Series或DataFrame之间的相关系数
- 传入一个Series将会返回一个相关系数值Series(针对各列进行计算)
In [40]: returns.corrwith(returns.IBM)Out[40]: AAPL 0.410011GOOG 0.390689IBM 1.000000MSFT 0.495980dtype: float64
- 传入一个DataFrame则会计算按列名配对的相关系数,这里,我们计算百分比变换与成交量的相关系数
In [43]: returns.corrwith(volume)Out[43]: AAPL -0.057549GOOG 0.062647IBM -0.007892MSFT -0.014245dtype: float64
- 传入axis=1 即按行进行计算,无论何时,在计算相关系数之前,所有数据项都会按照标签进行对齐
(2)唯一值、值计数以及成员资格
- 这类方法,我们可以从一维Series的值中提取信息
- 第一个函数可以得到Series中的唯一值数组
In [44]: obj = pd.Series(['c','a','d','a','a','b','b','c','c'])In [47]: uniques = obj.unique()In [48]: uniquesOut[48]: array(['c', 'a', 'd', 'b'], dtype=object)
- 返回的唯一值是未经排序的,如果需要的话,可以对结果再次进行排序
- value_counts用于计算一个Series中各值出现的频率
In [50]: uniques.sort()In [51]: uniquesOut[51]: array(['a', 'b', 'c', 'd'], dtype=object)In [52]: obj.value_counts()Out[52]: c 3a 3b 2d 1dtype: int64
- value_counts是Series是按值频率降序排列的
- value_counts还是一个顶级pandas方法,可用于任何数组或序列
In [53]: pd.value_counts(obj.values,sort=False)Out[53]: a 3c 3b 2d 1dtype: int64
- isin函数用于判断矢量化集合的成员资格
- 就是看obj中的每个元素是否在我们传入函数中的那个集合中
In [55]: mask = obj.isin(['a','c'])In [56]: maskOut[56]: 0 True1 True2 False3 True4 True5 False6 False7 True8 Truedtype: boolIn [57]: obj[mask]Out[57]: 0 c1 a3 a4 a7 c8 cdtype: object
- 唯一值、值计数、成员资格方法
- 将pandas.value_counts传给该DataFrame的apply函数
- 行索引就是该DataFrame中的所有唯一数据,该Dataframe的值就是出现的频率
In [58]: data = pd.DataFrame({'Qu1':[1,3,4,3,4], ....: 'Qu2':[2,3,1,2,3], ....: 'Qu3':[1,5,2,4,4]})In [59]: dataOut[59]: Qu1 Qu2 Qu30 1 2 11 3 3 52 4 1 23 3 2 44 4 3 4[5 rows x 3 columns]In [60]: result = data.apply(pd.value_counts).fillna(0)In [61]: resultOut[61]: Qu1 Qu2 Qu31 1 1 12 0 2 13 2 2 04 2 0 25 0 0 1[5 rows x 3 columns]
处理缺失数据:
- pandas使用浮点值NaN表示浮点和非浮点数组中的缺失数据,他只是一个便于被检测出来的标记而已
- python 内置的None 值也会被当做NA 处理
In [66]: string_data = pd.Series(['aardvark','artichoke',np.nan,'avocado'])In [67]: string_dataOut[67]: 0 aardvark1 artichoke2 NaN3 avocadodtype: objectIn [69]: string_data.isnull()Out[69]: 0 False1 False2 True3 Falsedtype: boolIn [70]: string_data[0] = NoneIn [71]: string_data.isnull()Out[71]: 0 True1 False2 True3 Falsedtype: bool
- NA处理方法
(1)滤除缺失数据
- dropna返回一个仅含非空数据和索引值的Series
- 通过布尔型索引也可以达到这个目的
In [72]: from numpy import nan as NAIn [73]: data = pd.Series([1,NA,3.5,NA,7])In [74]: data.dropna()Out[74]: 0 1.02 3.54 7.0dtype: float64In [75]: data[data.notnull()]Out[75]: 0 1.02 3.54 7.0dtype: float64
- 对于DataFrame 对象,事情就有点复杂了
- dropna默认丢弃任何含有缺失值的行
- 传入how=‘all' 将只丢弃全为NA的那些行
- 传入axis = 1 将删除全为NA的那些列
In [76]: data = pd.DataFrame([[1.,6.5,3.],[1.,NA,NA], ....: [NA,NA,NA],[NA,6.5,3.]])In [77]: cleaned = data.dropna()In [78]: dataOut[78]: 0 1 20 1 6.5 31 1 NaN NaN2 NaN NaN NaN3 NaN 6.5 3[4 rows x 3 columns]In [79]: cleanedOut[79]: 0 1 20 1 6.5 3[1 rows x 3 columns]In [80]: data.dropna(how='all')Out[80]: 0 1 20 1 6.5 31 1 NaN NaN3 NaN 6.5 3[3 rows x 3 columns]In [81]: data.dropna(axis=1,how='all')Out[81]: 0 1 20 1 6.5 31 1 NaN NaN2 NaN NaN NaN3 NaN 6.5 3[4 rows x 3 columns]
- 当你只想留下某些数据时,可以利用thresh 参数来设定
In [90]: df.ix[:4,1] = NA;df.ix[:3,2] = NAIn [91]: dfOut[91]: 0 1 20 0.739899 NaN NaN1 0.124309 NaN NaN2 0.960898 NaN NaN3 -0.059859 NaN NaN4 -1.917175 NaN -1.1226715 -0.073825 1.384257 -1.2663326 0.957087 0.185031 -1.241783[7 rows x 3 columns]In [92]: df.dropna(thresh=4)Out[92]: Empty DataFrameColumns: [0, 1, 2]Index: [][0 rows x 3 columns]In [93]: df.dropna(thresh=3)Out[93]: 0 1 25 -0.073825 1.384257 -1.2663326 0.957087 0.185031 -1.241783[2 rows x 3 columns]
(2)填充缺失数据
- fillna方法
In [97]: df.fillna(0)Out[97]: 0 1 20 0.739899 0.000000 0.0000001 0.124309 0.000000 0.0000002 0.960898 0.000000 0.0000003 -0.059859 0.000000 0.0000004 -1.917175 0.000000 -1.1226715 -0.073825 1.384257 -1.2663326 0.957087 0.185031 -1.241783[7 rows x 3 columns]In [99]: df.fillna({1:0.5,2:-1})Out[99]: 0 1 20 0.739899 0.500000 -1.0000001 0.124309 0.500000 -1.0000002 0.960898 0.500000 -1.0000003 -0.059859 0.500000 -1.0000004 -1.917175 0.500000 -1.1226715 -0.073825 1.384257 -1.2663326 0.957087 0.185031 -1.241783[7 rows x 3 columns]
- fillna 默认会返回新对象,但也可以对现有对象进行就地修改
In [100]: _ = df.fillna(0,inplace=True)In [101]: dfOut[101]: 0 1 20 0.739899 0.000000 0.0000001 0.124309 0.000000 0.0000002 0.960898 0.000000 0.0000003 -0.059859 0.000000 0.0000004 -1.917175 0.000000 -1.1226715 -0.073825 1.384257 -1.2663326 0.957087 0.185031 -1.241783[7 rows x 3 columns]
- fillna函数的参数
层次化索引:
- 使用低维度形式处理高维度数据
- 创建一个Series,并用一个由列表或数组组成的列表作为索引
- 这就是带有MultiIndex索引的Series的格式化输出形式
- 索引之间的间隔表示直接使用上面的标签
- 对于一个层次化索引的对象,选取数据子集的操作很简单
In [105]: data = pd.Series(np.random.randn(10), .....: index = [['a','a','a','b','b','b','c','c','d','d'], .....: [1,2,3,1,2,3,1,2,2,3]])In [106]: dataOut[106]: a 1 -0.237206 2 -0.992311 3 1.685961b 1 0.987261 2 -1.166006 3 -0.962065c 1 -1.071484 2 0.393728d 2 0.793652 3 -0.223266dtype: float64In [107]: data.indexOut[107]: MultiIndex(levels=[[u'a', u'b', u'c', u'd'], [1, 2, 3]], labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 1, 2]])In [108]: data['b']Out[108]: 1 0.9872612 -1.1660063 -0.962065dtype: float64
- 可以在“内层”中进行选取
In [109]: data[:,2]Out[109]: a -0.992311b -1.166006c 0.393728d 0.793652dtype: float64
- 层次化索引在数据重塑和基于分组的操作中扮演着重要的角色
- 可以利用unstack 方法被重新安排到一个DataFrame中
In [110]: data.unstack()Out[110]: 1 2 3a -0.237206 -0.992311 1.685961b 0.987261 -1.166006 -0.962065c -1.071484 0.393728 NaNd NaN 0.793652 -0.223266[4 rows x 3 columns]In [111]: data.unstack().stack()Out[111]: a 1 -0.237206 2 -0.992311 3 1.685961b 1 0.987261 2 -1.166006 3 -0.962065c 1 -1.071484 2 0.393728d 2 0.793652 3 -0.223266dtype: float64
- 对于一个DataFrame,每条轴都可以有分层索引
- 每层都可以有名字;如果制定了名称,他们就会显示在控制台输出中
- 不要将索引名跟轴标签混为一谈
In [113]: frame = pd.DataFrame(np.arange(12).reshape((4,3)),index = [['a','a','b','b'],[1,2,1,2]],columns = [['Ohio',"Ohio",'Colorado'],['Green','Red','Green']])In [114]: frameOut[114]: Ohio Colorado Green Red Greena 1 0 1 2 2 3 4 5b 1 6 7 8 2 9 10 11[4 rows x 3 columns]In [115]: frame.index.names = ['key1','key2']In [116]: frame.columns.names = ['state','color']In [117]: frameOut[117]: state Ohio Coloradocolor Green Red Greenkey1 key2 a 1 0 1 2 2 3 4 5b 1 6 7 8 2 9 10 11[4 rows x 3 columns]
- 可以单独创建MultiIndex 然后复用,上面那个DataFrame中的(分级)列可以这样创建
In [125]: col = pd.MultiIndex.from_arrays([['Ohio','Ohio','Colorado'],['Green','Red','Green']],names=['state','color'])In [126]: frame2 = pd.DataFrame(np.arange(12).reshape((4,3)),index = [['a','a','b','b'],[1,2,1,2]],columns = col )In [127]: frame2Out[127]: state Ohio Coloradocolor Green Red Greena 1 0 1 2 2 3 4 5b 1 6 7 8 2 9 10 11[4 rows x 3 columns]
(1)重排分级顺序
- swaplevel 接受两个级别编号或名称,并返回一个互换了级别的新对象
In [129]: frame.swaplevel('key1','key2')Out[129]: state Ohio Coloradocolor Green Red Greenkey2 key1 1 a 0 1 22 a 3 4 51 b 6 7 82 b 9 10 11[4 rows x 3 columns]
- sortlevel 则根据单个级别中的值对数据进行排序
- 交换级别时,常常也会用到sortlevel
In [130]: frame.sortlevel(1)Out[130]: state Ohio Coloradocolor Green Red Greenkey1 key2 a 1 0 1 2b 1 6 7 8a 2 3 4 5b 2 9 10 11[4 rows x 3 columns]In [131]: frameOut[131]: state Ohio Coloradocolor Green Red Greenkey1 key2 a 1 0 1 2 2 3 4 5b 1 6 7 8 2 9 10 11[4 rows x 3 columns]In [132]: frame.sortlevel(0)Out[132]: state Ohio Coloradocolor Green Red Greenkey1 key2 a 1 0 1 2 2 3 4 5b 1 6 7 8 2 9 10 11[4 rows x 3 columns]
In [134]: frame.swaplevel(0,1)Out[134]: state Ohio Coloradocolor Green Red Greenkey2 key1 1 a 0 1 22 a 3 4 51 b 6 7 82 b 9 10 11[4 rows x 3 columns]In [135]: frameOut[135]: state Ohio Coloradocolor Green Red Greenkey1 key2 a 1 0 1 2 2 3 4 5b 1 6 7 8 2 9 10 11[4 rows x 3 columns]In [136]: frame.swaplevel(0,1).sortlevel(0)Out[136]: state Ohio Coloradocolor Green Red Greenkey2 key1 1 a 0 1 2 b 6 7 82 a 3 4 5 b 9 10 11[4 rows x 3 columns]
(2)根据级别汇总统计
- 我们可以根据行或列上的级别来进行求和
In [137]: frame.sum(level='key2')Out[137]: state Ohio Coloradocolor Green Red Greenkey2 1 6 8 102 12 14 16[2 rows x 3 columns]In [138]: frame.sum(level='color',axis=1)Out[138]: color Green Redkey1 key2 a 1 2 1 2 8 4b 1 14 7 2 20 10[4 rows x 2 columns]
(3)使用DataFrame的列
- DataFrame 的 set_index 函数会将其一个或多个列转换为行索引,并创建一个新的DataFrame
In [139]: frame = pd.DataFrame({'a':range(7),'b':range(7,0,-1), .....: 'c':['one','one','one','two','two','two','two'], .....: 'd':[0,1,2,0,1,2,3]})In [140]: frameOut[140]: a b c d0 0 7 one 01 1 6 one 12 2 5 one 23 3 4 two 04 4 3 two 15 5 2 two 26 6 1 two 3[7 rows x 4 columns]In [141]: frame2 = frame.set_index(['c','d'])In [142]: frame2Out[142]: a bc d one 0 0 7 1 1 6 2 2 5two 0 3 4 1 4 3 2 5 2 3 6 1[7 rows x 2 columns]
- 默认情况下,那些列会从DataFrame中移除,但也可以将其保留下来
- reset_index 的功能跟set_index刚好相反,层次化索引的级别会被转移到列里面
In [143]: frame.set_index(['c','d'],drop=False)Out[143]: a b c dc d one 0 0 7 one 0 1 1 6 one 1 2 2 5 one 2two 0 3 4 two 0 1 4 3 two 1 2 5 2 two 2 3 6 1 two 3[7 rows x 4 columns]In [144]: frame2.reset_index()Out[144]: c d a b0 one 0 0 71 one 1 1 62 one 2 2 53 two 0 3 44 two 1 4 35 two 2 5 26 two 3 6 1[7 rows x 4 columns]
转载地址:https://lipenglin.blog.csdn.net/article/details/51345369 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
做的很好,不错不错
[***.243.131.199]2024年04月14日 18时28分35秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
xss-labs详解(上)1-10
2019-04-30
xss-labs详解(下)11-20
2019-04-30
攻防世界web进阶区ics-05详解
2019-04-30
攻防世界web进阶区FlatScience详解
2019-04-30
攻防世界web进阶区ics-04详解
2019-04-30
攻防世界web进阶区Cat详解
2019-04-30
攻防世界web进阶区bug详解
2019-04-30
攻防世界web进阶区ics-07详解
2019-04-30
攻防世界web进阶区unfinish详解
2019-04-30
攻防世界web进阶区i-got-id-200超详解
2021-07-03
sql注入总结学习
2021-07-03
leetcode46 全排列
2021-07-03
leetcode121 买卖股票的最佳时机
2021-07-03
leetcode 122 买卖股票的最佳时机II
2021-07-03
leetcode 309 最佳买卖股票含冷冻期
2021-07-03
leetcode 714 买卖股票的最佳时机含手续费
2021-07-03
leetcode3 无重复字符的最长子串
2021-07-03
leetcode 76 最小覆盖子串
2021-07-03
leetcode 1143. 最长公共子序列
2021-07-03
leetcode 83. 删除排序链表中的重复元素
2021-07-03