标签:重命名 25 10 df 18 索引 3.0 pandas Out
一、重命名轴索引
与Series对象类似,轴索引也有一个map方法:
In [83]: df = pd.DataFrame(np.arange(12).reshape((3, 4)), ...: index=['Ohio', 'Colorado', 'New York'], ...: columns=['one', 'two', 'three', 'four']) ...: In [84]: transform = lambda x: x[:4].upper() # 截取前4个字符并大写 In [85]: df.index.map(transform) # map的结果 Out[85]: Index(['OHIO', 'COLO', 'NEW '], dtype='object') In [86]: df.index = df.index.map(transform) #用结果修改原来的index In [87]: df Out[87]: one two three four OHIO 0 1 2 3 COLO 4 5 6 7 NEW 8 9 10 11
还可以使用rename方法修改索引,且不修改原数据:
# 参数的值是对索引进行修改的处理函数,比如str.title In [88]: df.rename(index=str.title, columns=str.upper) Out[88]: ONE TWO THREE FOUR Ohio 0 1 2 3 Colo 4 5 6 7 New 8 9 10 11 In [89]: df # 原值未变 Out[89]: one two three four OHIO 0 1 2 3 COLO 4 5 6 7 NEW 8 9 10 11
或者使用字典的方式,将指定的索引重命名为新值:
In [90]: df.rename(index={'OHIO': 'INDIANA'}, ...: columns={'three': 'peekaboo'}) ...: Out[90]: one two peekaboo four INDIANA 0 1 2 3 COLO 4 5 6 7 NEW 8 9 10 11 In [91]: df Out[91]: one two three four OHIO 0 1 2 3 COLO 4 5 6 7 NEW 8 9 10 11
照样可以使用inplace=True修改原数据集。
二、离散化
离散化,就是将连续值转换为一个个区间内,形成一个个分隔的‘箱子’。假设我们有下面的一群人的年龄数据,想将它们进行分组,并放入离散的年龄箱内:
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
我们预先定义18~25、26~35、36~60以及61及以上等若干组。
Pandas提供一个cut方法,帮助我们实现分箱功能:
In [93]: bins = [18,25,35,60,100] In [94]: cats = pd.cut(ages,bins) In [95]: cats Out[95]: [(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]] Length: 12 Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
返回的cats是一个特殊的Categorical对象,输出描述了12个年龄值分别处于哪个箱子中。cats包含一系列的属性:
In [96]: cats.codes Out[96]: array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8) In [97]: cats.categories Out[97]: IntervalIndex([(18, 25], (25, 35], (35, 60], (60, 100]] closed='right', dtype='interval[int64]') In [98]: cats.describe Out[98]: <bound method Categorical.describe of [(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]] Length: 12 Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]> In [99]: pd.value_counts(cats) # 各个箱子的数量 Out[99]: (18, 25] 5 (35, 60] 3 (25, 35] 3 (60, 100] 1 dtype: int64
分箱的区间通常是左开右闭的,如果想变成左闭右开,请设置参数right=False。
可以定义labels参数,来自定义每种箱子的名称:
In [100]: group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']^M ...: pd.cut(ages, bins, labels=group_names) Out[100]: [Youth, Youth, Youth, YoungAdult, Youth, ..., YoungAdult, Senior, MiddleAged, MiddleAged, YoungAdult] Length: 12 Categories (4, object): [Youth < YoungAdult < MiddleAged < Senior]
如果你不提供分箱的区间定义,而是直接要求分隔成整数个等分区间,可以这么做:
In [101]: d =np.random.rand(20) In [102]: d Out[102]: array([0.83732945, 0.0850416 , 0.66540597, 0.90479238, 0.99222014, 0.39409122, 0.91896172, 0.87163655, 0.31374598, 0.27726111, 0.7716572 , 0.79131961, 0.42805445, 0.29934685, 0.19077374, 0.79701771, 0.93789892, 0.93536338, 0.32299602, 0.305671 ]) In [103]: pd.cut(d, 4, precision=2) # 精度限制在两位 Out[103]: [(0.77, 0.99], (0.084, 0.31], (0.54, 0.77], (0.77, 0.99], (0.77, 0.99], ..., (0.77, 0.99], (0.77, 0.99], (0.77, 0.99], (0.31, 0.54], (0.084, 0.31]] Length: 20 Categories (4, interval[float64]): [(0.084, 0.31] < (0.31, 0.54] < (0.54, 0.77] < (0.77, 0.99]]
cut函数执行的时候,分箱区间要么是你指定的,要么是均匀大小的。还有一种分箱方法叫做qcut,它是使用样本的分位数来分割的,而不是样本值的大小。比如下面的操作,将使每个箱子中元素的个数相等:
In [104]: data = np.random.randn(1000) In [105]: cats = pd.qcut(data,4) In [106]: cats Out[106]: [(0.644, 2.83], (-0.0344, 0.644], (-0.0344, 0.644], (-0.734, -0.0344], (-0.734, -0.0344], ..., (-3.327, -0.734], (-0.734, -0.0344], (0.644, 2.83], (-0.734, -0.0344], (-0.0344, 0.644]] Length: 1000 Categories (4, interval[float64]): [(-3.327, -0.734] < (-0.734, -0.0344] < (-0.0344, 0.644] < (0.644, 2.83]] In [108]: pd.value_counts(cats) # 各箱子中的元素个数相同 Out[108]: (0.644, 2.83] 250 (-0.0344, 0.644] 250 (-0.734, -0.0344] 250 (-3.327, -0.734] 250 dtype: int64
qcut还可以自定义0~1之间的分位数:
pd.qcut(data, [0, 0.1, 0.5, 0.9, 1.])
离散化函数对于分位数和分组分析特别有用。
三、异常值处理
检测和过滤异常值是数据清洗过程中非常重要的一步。比如你手里有个一万成人的身高数据,其中有几个3m以上,1m以下的数据,这都是属于异常值,需要被过滤掉。
我们来看下面的一组正态分布的数据:
In [109]: df = pd.DataFrame(np.random.randn(1000, 4)) In [110]: df.describe() Out[110]: 0 1 2 3 count 1000.000000 1000.000000 1000.000000 1000.000000 mean -0.001764 0.023018 0.038956 0.016735 std 0.998835 1.041113 1.025342 1.019077 min -3.035805 -3.056706 -2.857154 -2.922755 25% -0.654426 -0.695994 -0.712627 -0.702766 50% -0.005015 0.011862 0.020562 -0.041231 75% 0.660182 0.683478 0.732590 0.758038 max 3.323073 3.701470 3.280375 3.997876
如果你想找出第二列数据中绝对值大于3的元素:
In [113]: col = df[2] In [114]: col[np.abs(col) > 3] Out[114]: 30 3.091161 113 3.280375 Name: 2, dtype: float64
如果要选出所有行内有值大于3或小于-3的行,可以使用下面的any方法搭配:
In [125]: df[(np.abs(df)>3).any(1)] Out[125]: 0 1 2 3 28 0.008674 0.046048 -0.171580 3.997876 30 0.709758 -1.871982 3.091161 -0.819429 113 0.432223 -0.675313 3.280375 0.841355 169 3.323073 -0.608988 0.685795 -0.710693 177 -1.514524 -3.056706 -0.760937 1.300434 322 3.296765 0.971996 0.114804 1.855576 410 3.246140 -0.039501 1.530122 1.502243 496 -3.035805 -0.535662 0.703911 0.916483 575 -0.127245 3.701470 -0.642512 0.281001 720 3.045646 1.266809 1.263198 1.429049 799 0.523183 -0.246954 1.132868 3.141117
首先,我们对整个df取绝对值,然后和3比较,形成一个bool的DataFrame,再使用any在行方向(参数1的作用)进行判断是否有True的存在,如果有,则保存在一个Series中,最后,用这个Series作为行号取df取出对应的行。
我们还可以将绝对值大于3的数分别设置为+3和-3,只需要使用np.sign(x)函数,这个函数根据x的符号分别生成+1和-1:
In [127]: df[np.abs(df) > 3] = np.sign(df) * 3 In [130]: df.describe() Out[130]: 0 1 2 3 count 1000.000000 1000.000000 1000.000000 1000.000000 mean -0.002640 0.022374 0.038584 0.015596 std 0.995851 1.038699 1.024224 1.015232 min -3.000000 -3.000000 -2.857154 -2.922755 25% -0.654426 -0.695994 -0.712627 -0.702766 50% -0.005015 0.011862 0.020562 -0.041231 75% 0.660182 0.683478 0.732590 0.758038 max 3.000000 3.000000 3.000000 3.000000 In [133]: (np.sign(df)*3).head() Out[133]: 0 1 2 3 0 3.0 3.0 -3.0 -3.0 1 3.0 3.0 -3.0 -3.0 2 -3.0 -3.0 -3.0 -3.0 3 -3.0 -3.0 3.0 -3.0 4 3.0 -3.0 3.0 -3.0
四、随机抽样
有时候,我们需要打乱原有的数据顺序,让数据看起来像现实中比较混沌、自然的样子。这里推荐一个permutation操作,它来自numpy.random,可以随机生成一个序列:
In [134]: order = np.random.permutation(5) # 5个数 In [135]: order Out[135]: array([3, 4, 1, 2, 0])
然后我们用它处理下面的df,让行的顺序变成和order的一样:
In [136]: df = pd.DataFrame(np.arange(5 * 4).reshape((5, 4))) In [137]: df Out[137]: 0 1 2 3 0 0 1 2 3 1 4 5 6 7 2 8 9 10 11 3 12 13 14 15 4 16 17 18 19 In [138]: df.take(order) # Out[138]: 0 1 2 3 3 12 13 14 15 4 16 17 18 19 1 4 5 6 7 2 8 9 10 11 0 0 1 2 3 In [139]: df.iloc[order] # 同上 Out[139]: 0 1 2 3 3 12 13 14 15 4 16 17 18 19 1 4 5 6 7 2 8 9 10 11 0 0 1 2 3
可以看到,通过take函数,使用order作为参数,打乱了df的行顺序。
还有一种叫做抽样的操作,从原样本集合中抽取一部分形成新的样本集合,分重复抽样和不重复抽样。pandas提供的sample函数帮我们实现了这一功能:
In [140]: df.sample(n=3) Out[140]: 0 1 2 3 0 0 1 2 3 4 16 17 18 19 1 4 5 6 7 In [141]: df.sample(n=10) --------------------------------------------------------------------------- ValueError Traceback (most recent call last) In [142]: df.sample(n=10,replace=True) Out[142]: 0 1 2 3 3 12 13 14 15 2 8 9 10 11 2 8 9 10 11 0 0 1 2 3 3 12 13 14 15 0 0 1 2 3 2 8 9 10 11 4 16 17 18 19 1 4 5 6 7 3 12 13 14 15
- n=3:指定从原来数据中抽取3行
- n=10:弹出异常,因为原数据不够10行
- replace=True:可以重复抽取,这样10行可以,因为有重复
很明显,取样的操作是针对每行的。前面我们说过,一行就是一条记录,一个样本。
标签:重命名,25,10,df,18,索引,3.0,pandas,Out 来源: https://www.cnblogs.com/lavender1221/p/12730311.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。