推荐书: Python开发最佳实践

pandas数据分析100道练习题-第三部分

分享时@该用户已经被封, 我就能回答你的问题奥!

文章目录
  1. 1. 检查dataframe是否有缺失值
  2. 2. 统计dataframe中每列缺失值的数量
  3. 3. dataframe用每列的平均值取代缺失值
  4. 4. 从dataframe中获取某一列, 并返回一个dataframe
  5. 5. dataframe如何改变列的顺序
  6. 6. 设置dataframe输出的行数和列数
  7. 7. 设置dataframe输出时不使用科学记数法
  8. 8. 设置dataframe输出百分比数据
  9. 9. 使用多个列创建唯一索引(index)
  10. 10. 获取第n大的数所在行
  11. 11. dataframe获取行之和大于100的数据, 并返回最后的两行
  12. 12. 如何从系列或数据框列中查找和限制异常值
  13. 13. 如何在删除负值后将dataframe重新整形为最大可能的正方形
  14. 14. 交换dataframe的两行
  15. 15. dataframe行倒序排序
  16. 16. 对分类数据进行one-hot编码
  17. 17. 哪个列包含每行的最大值
  18. 18. 计算 每行的最近行(使用欧几里得距离)


这篇文章收集了网友们使用pandas进行数据分析时经常遇到的问题, 这些问题也可以检验你使用pandas的熟练程度, 所以他们更像是一个学习教材, 掌握这些技能, 可以使你数据数据分析的工作事半功倍。

下面是第三部分:

检查dataframe是否有缺失值

1
2
3
4
5
6
7
8
9
10
11
import pandas as pd
import numpy as np

df = pd.DataFrame({
'a':[1.2,2,3,4],
'b':list('abcd')
})

print('缺失:', df.isnull().values.any())
df.iat[0,0] = np.nan
print('缺失:', df.isnull().values.any())
输出(stream):
缺失: False
缺失: True

统计dataframe中每列缺失值的数量

1
df.apply(lambda x: x.isnull().sum())
输出(plain):
a 1
b 0
dtype: int64

dataframe用每列的平均值取代缺失值

1
2
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/Cars93_miss.csv')
df[['Min.Price', 'Max.Price']].head()
输出(html):
Min.Price Max.Price
0 12.9 18.8
1 29.2 38.7
2 25.9 32.3
3 NaN 44.6
4 NaN NaN
1
2
# 仅使用['Min.Price', 'Max.Price']这两列演示
df[['Min.Price', 'Max.Price']].apply(lambda x: x.fillna(x.mean())).head()
输出(html):
Min.Price Max.Price
0 12.900000 18.800000
1 29.200000 38.700000
2 25.900000 32.300000
3 17.118605 44.600000
4 17.118605 21.459091

从dataframe中获取某一列, 并返回一个dataframe

1
2
# 只要传入一个list作为切片
df[['Manufacturer']].head()
输出(html):
Manufacturer
0 Acura
1 NaN
2 Audi
3 Audi
4 BMW

dataframe如何改变列的顺序

1
2
df = pd.DataFrame(np.arange(20).reshape(-1, 5), columns=list('abcde'))
df.head()
输出(html):
a b c d e
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
1
df[list('cbdae')]
输出(html):
c b d a e
0 2 1 3 0 4
1 7 6 8 5 9
2 12 11 13 10 14
3 17 16 18 15 19

设置dataframe输出的行数和列数

1
2
# 设置之前
df
输出(html):
a b c d e
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
1
2
3
4
pd.set_option('display.max_columns', 4)
pd.set_option('display.max_rows', 4)
# 设置之后
df
输出(html):
a b ... d e
0 0 1 ... 3 4
1 5 6 ... 8 9
2 10 11 ... 13 14
3 15 16 ... 18 19

4 rows × 5 columns

1
2
pd.set_option('display.max_columns', 10)
pd.set_option('display.max_rows', 10)

设置dataframe输出时不使用科学记数法

1
pd.DataFrame(np.random.random(4)**10, columns=['random'])
输出(html):
random
0 4.285027e-07
1 1.580650e-05
2 2.049461e-01
3 6.873938e-06
1
2
pd.set_option('display.float_format', lambda x: '%.4f' % x)
pd.DataFrame(np.random.random(4)**10, columns=['random'])
输出(html):
random
0 0.0000
1 0.9207
2 0.0209
3 0.0000
1
2
3
# 恢复默认值
pd.set_option('display.float_format', None)
pd.DataFrame(np.random.random(4)**10, columns=['random'])
输出(html):
random
0 0.004970
1 0.018763
2 0.000058
3 0.252180

设置dataframe输出百分比数据

1
2
df = pd.DataFrame(np.random.random(4), columns=['random'])
df
输出(html):
random
0 0.343280
1 0.700357
2 0.885307
3 0.932272
1
df.style.format({'random':'{0:.2%}'.format})
输出(html):
random
0 34.33%
1 70.04%
2 88.53%
3 93.23%

知识点:

使用百分号可以自动将数据转换为百分比格式:
'{0:.2%}'.format(0.555555)

更多字符串格式化问题,可以看这篇专题: python3字符串format最佳实践

使用多个列创建唯一索引(index)

1
2
3
df = pd.read_csv(
'https://raw.githubusercontent.com/selva86/datasets/master/Cars93_miss.csv',
usecols=[0,1,2,3,5])
1
2
3
df[['Manufacturer', 'Model', 'Type']] = df[['Manufacturer', 'Model', 'Type']].fillna('missing')
df.index = df.Manufacturer + '_' + df.Model + '_' + df.Type
print(df.index.is_unique)
输出(stream):
True

获取第n大的数所在行

1
2
3
4
df = pd.DataFrame(
np.random.randint(1, 30, 30).reshape(10,-1),
columns=list('abc'))
df['a']
输出(plain):
0 21
1 17
2 19
3 3
4 2
5 3
6 10
7 5
8 25
9 12
Name: a, dtype: int32
1
2
# 使用行号排序
df['a'].argsort()
输出(plain):
0 4
1 3
2 5
3 7
4 6
5 9
6 1
7 2
8 0
9 8
Name: a, dtype: int64
1
2
3
# 可以这样看到原始数据的排序

df['a'][df['a'].argsort()]
输出(plain):
4 2
3 3
5 3
7 5
6 10
9 12
1 17
2 19
0 21
8 25
Name: a, dtype: int32
1
2
n = 5
df['a'].argsort()[::-1][n]
输出(plain):
3

dataframe获取行之和大于100的数据, 并返回最后的两行

1
2
3
4
df = pd.DataFrame(np.random.randint(10, 40, 60).reshape(-1, 4))
rowsums = df.apply(np.sum, axis=1)
last_two_rows = df.iloc[np.where(rowsums > 100)[0][-2:], :]
last_two_rows
输出(html):
0 1 2 3
13 39 31 35 15
14 30 22 25 31

如何从系列或数据框列中查找和限制异常值

用相应的5%分位数和95%分位数值替换低于5%分位数和大于95%分位数的所有值

1
2
3
4
5
6
7
8
9
10
11
12
# Input
ser = pd.Series(np.logspace(-2, 2, 30))

# Solution
def cap_outliers(ser, low_perc, high_perc):
low, high = ser.quantile([low_perc, high_perc])
print(low_perc, '%ile: ', low, '|', high_perc, '%ile: ', high)
ser[ser < low] = low
ser[ser > high] = high
return(ser)

capped_ser = cap_outliers(ser, .05, .95)
输出(stream):
0.05 %ile: 0.016049294076965887 | 0.95 %ile: 63.876672220183934

如何在删除负值后将dataframe重新整形为最大可能的正方形

将df重塑为最大可能的正方形,并删除负值。如果需要,删除最小值。结果中正数的顺序应保持与原始顺序相同。

1
2
df = pd.DataFrame(np.random.randint(-20, 50, 100).reshape(10,-1))
print(df)
输出(stream):
0 1 2 3 4 5 6 7 8 9
0 12 -6 -15 14 33 -9 -14 46 7 6
1 23 -5 13 22 -10 35 -8 8 -20 34
2 19 49 18 -1 5 22 38 -5 27 34
3 -12 47 21 9 45 18 3 -10 27 42
4 48 32 41 -14 5 40 33 -3 10 11
5 17 -2 13 47 28 5 24 26 -7 10
6 49 21 14 -16 12 -17 3 43 8 -10
7 17 -19 -14 2 -8 -10 1 25 -9 48
8 25 46 -7 36 -13 18 42 31 49 37
9 2 25 47 28 9 49 10 44 -15 12
1
2
3
4
5
# 步骤1:删除负数

arr = df[df > 0].values.flatten()
arr_qualified = arr[~np.isnan(arr)]
arr_qualified
输出(plain):
array([12., 14., 33., 46., 7., 6., 23., 13., 22., 35., 8., 34., 19.,
49., 18., 5., 22., 38., 27., 34., 47., 21., 9., 45., 18., 3.,
27., 42., 48., 32., 41., 5., 40., 33., 10., 11., 17., 13., 47.,
28., 5., 24., 26., 10., 49., 21., 14., 12., 3., 43., 8., 17.,
2., 1., 25., 48., 25., 46., 36., 18., 42., 31., 49., 37., 2.,
25., 47., 28., 9., 49., 10., 44., 12.])
1
2
3
4
# 步骤2: 计算正方形的边长

n = int(np.floor(arr_qualified.shape[0]**.5))
n
输出(plain):
8
1
2
3
4
# 步骤3: 整形为要求的正方形
top_indexes = np.argsort(arr_qualified)[::-1]
output = np.take(arr_qualified, sorted(top_indexes[:n**2])).reshape(n, -1)
print(output)
输出(stream):
[[12. 14. 33. 46. 7. 23. 13. 22.]
[35. 8. 34. 19. 49. 18. 22. 38.]
[27. 34. 47. 21. 9. 45. 18. 27.]
[42. 48. 32. 41. 40. 33. 10. 11.]
[17. 13. 47. 28. 24. 26. 10. 49.]
[21. 14. 12. 43. 8. 17. 25. 48.]
[25. 46. 36. 18. 42. 31. 49. 37.]
[25. 47. 28. 9. 49. 10. 44. 12.]]

交换dataframe的两行

把第一行和第二行数据交换

1
2
df = pd.DataFrame(np.arange(25).reshape(5, -1))
df
输出(html):
0 1 2 3 4
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
4 20 21 22 23 24
1
2
3
a, b = df.iloc[1, :].copy(), df.iloc[2, :].copy()
df.iloc[1, :], df.iloc[2, :] = b, a
df
输出(html):
0 1 2 3 4
0 0 1 2 3 4
1 10 11 12 13 14
2 5 6 7 8 9
3 15 16 17 18 19
4 20 21 22 23 24

dataframe行倒序排序

1
df.iloc[::-1, :]
输出(html):
0 1 2 3 4
4 20 21 22 23 24
3 15 16 17 18 19
2 5 6 7 8 9
1 10 11 12 13 14
0 0 1 2 3 4

对分类数据进行one-hot编码

经常用于逻辑回归

1
2
df = pd.DataFrame(np.arange(25).reshape(5,-1), columns=list('abcde'))
df
输出(html):
a b c d e
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
4 20 21 22 23 24
1
pd.concat([pd.get_dummies(df['a']), df[list('bcde')]], axis=1)
输出(html):
0 5 10 15 20 b c d e
0 1 0 0 0 0 1 2 3 4
1 0 1 0 0 0 6 7 8 9
2 0 0 1 0 0 11 12 13 14
3 0 0 0 1 0 16 17 18 19
4 0 0 0 0 1 21 22 23 24

哪个列包含每行的最大值

求行最大值所在的列

1
2
df = pd.DataFrame(np.random.randint(1,100, 40).reshape(10, -1))
df.apply(np.argmax, axis=1)
输出(stream):
d:\mysites\deeplearning.ai-master\.env\lib\site-packages\numpy\core\fromnumeric.py:52: FutureWarning: 'argmax' is deprecated, use 'idxmax' instead. The behavior of 'argmax'
will be corrected to return the positional maximum in the future.
Use 'series.values.argmax' to get the position of the maximum now.
return getattr(obj, method)(*args, **kwds)
输出(plain):
0 3
1 1
2 3
3 0
4 2
5 0
6 0
7 2
8 2
9 0
dtype: int64

计算 每行的最近行(使用欧几里得距离)

1
2
3
4
5
6
7
8
nearest = {}
for i, row in df.iterrows():
c = ((df - row)**2).sum(axis = 1).argsort()
for j in c:
if j != i:
break
nearest[i] = j
print(nearest)
输出(stream):
{0: 7, 1: 7, 2: 6, 3: 5, 4: 8, 5: 4, 6: 2, 7: 0, 8: 4, 9: 3}

今天的教程就到此为止了, 希望大家关注我的小站mlln.cn, 后面还会有关于pandas系列的练习题, 希望这些工作能帮助你学习pandas. 如果你有什么意见或者建议, 请在微博@该用户已经被封, 并附带本文链接。

注意
本文由jupyter notebook转换而来, 您可以在这里下载notebook
有问题可以直接在下方留言
或者给我发邮件675495787[at]qq.com
请记住我的网址: mlln.cn 或者 jupyter.cn