目前来说,如果没有Pandas的话,我工作起来会很吃力的。我很多时间都在处理和分析表格数据,pandas是我工作流程中很重要的一个部分。我想快速的展示几段我的副产品climatic中的代码片段,它展示了pandas的一些相关的功能与作用,然后深入了解在后台到底发生了些什么。
如果你对修补这个例子中的数据感兴趣的话,看看这个在climatic repo中的文件夹的例子。这里面有些例子的脚本也列出了怎么样使用climatic去操作数据。
首先,我要用climatic通过一个关于pandas的拥有有一些具有方便处理列头的read_tabl的e简单的外包来导入一些数据:
1import pandas as pd
2import numpy as np
3import climatic as cl
4
5walsenburg = cl.MetMast()
6walsenburg.wind_import(r"CO_Walsenburg_South_Data.txt",
7header_row=0, time_col=0,
8delimiter="\t", smart_headers=True)
climatic会将这些头文件解析成拥有一个属性和高度的元组。为的是在以后用pandas MultiIndexl来处理。接下来的话呢,我们把所有的风的出现频率的数据存在一个箱子里。
1freq_bins = np.arange(0, 375, 15)
2walsenburg.binned(column=("WD Mean 1", 49), bins=freq_bins, stat="mean",
3plot=("WS Mean 1", 50))
这将会给我们一个matplotlib关于WS Mean 1信号的绘图,按照部分来平均处理:
诺,现在在后面发生了什么呢?其实我们只用了不多于20行的代码就实现了这个功能。首先,我们拿出我们的数据中的一部分来分析,这样分析起来更简单一些,然后使用numpy来建立起一个小小的映射。
01import numpy as np
02
03#Turn a few columns into a new DataFrame
04data = pd.DataFrame({"Wind Speed 1": walsenburg.data[("WS Mean 1", 50.0)],
05"Wind Speed 2": walsenburg.data[("WS Mean 2", 50.0)],
06"Wind Dir 1": walsenburg.data[("WD Mean 1", 49.0)],
07"Wind Dir 2": walsenburg.data[("WD Mean 2", 38.0)]},
08index=walsenburg.data.index)
09
10#Write a short mapper that bins data
11def map_bin(x, bins):
12kwargs = {}
13if x == max(bins):
14kwargs["right"] = True
15bin = bins[np.digitize([x], bins, **kwargs)[0]]
16bin_lower = bins[np.digitize([x], bins, **kwargs)[0]-1]
17return "[{0}-{1}]".format(bin_lower, bin)
实际上是np.digitize在处理我们的重要的任务,它把我们一开始存在箱子中的X的值用括号的方式隔开了,为了强调如果X和最大箱子是一样的边缘情况,kwargs是有必要的,所以,为了把它加进来,我们需要在np.digitize中设置right=TRUE。
让我们来看看我们的映射程序吧:
1>>>map_bin(274, freq_bins)
2"[270-285]"
3>>>map_bin(60, freq_bins) #np.digitize defaults to right=False
4"[60-75]"
5>>>map_bin(360, freq_bins) #Edge case works!
6"[345-360]"
我们现在可以把我们的数据映射了: 01>>>data[:10]
02Wind Dir 1 Wind Dir 2 Wind Speed 1 Wind Speed 2
03Date & Time Stamp
04-06-01 14:00:00 245 261 12.05 12.26
05-06-01 14:10:00 244 258 11.48 11.60
06-06-01 14:20:00 245 260 14.19 14.39
07-06-01 14:30:00 249 268 13.21 13.43
08-06-01 14:40:00 246 263 11.92 12.12
09-06-01 14:50:00 235 255 11.90 12.05
10-06-01 15:00:00 232 249 12.78 12.92
11-06-01 15:10:00 234 252 13.27 13.40
12-06-01 15:20:00 234 252 14.05 14.24
13-06-01 15:30:00 233 251 13.32 13.48
14
15>>>data = data.dropna() #The mapper won"t be happy with NA values
16>>>data["Binned"] = data["Wind Dir 1"].apply(map_bin, bins=freq_bins)
17>>>data[["Wind Dir 1","Binned"]][:10]
18Wind Dir 1 Binned
19Date & Time Stamp
20-06-01 14:00:00 245 [240-255]
21-06-01 14:10:00 244 [240-255]
22-06-01 14:20:00 245 [240-255]
23-06-01 14:30:00 249 [240-255]
24-06-01 14:40:00 246 [240-255]
25-06-01 14:50:00 235 [225-240]
26-06-01 15:00:00 232 [225-240]
27-06-01 15:10:00 234 [225-240]
28-06-01 15:20:00 234 [225-240]
29-06-01 15:30:00 233 [225-240]
最后,我们把”Binned“数据分组,然后把每个箱子中的数据平均化: 01>>>grouped = data.groupby("Binned")
02>>>grouped_data = grouped.mean()
03>>>grouped_data.head()
04Wind Dir 1 Wind Dir 2 Wind Speed 1 Wind Speed 2
05Binned
06[0-15] 6.822575 31.094926 4.573297 4.371899
07[105-120] 111.928729 132.076001 5.626556 6.024371
08[120-135] 126.822383 146.176534 5.613520 5.835964
09[135-150] 141.683526 162.210983 5.617823 5.780949
10[15-30] 21.533770 45.891117 4.295620 4.198170
11
12#Close, but lets rearrange that index...
13
14>>>step = freq_bins[1]-freq_bins[0]
15>>>new_index = ["[{0}-{1}]".format(x, x+step) for x in freq_bins]
16>>>new_index.pop(-1) #We dont need [360-375]...
17>>>grouped_data = grouped_data.reindex(new_index)
18
19Wind Dir 1 Wind Dir 2 Wind Speed 1 Wind Speed 2
20[0-15] 6.822575 31.094926 4.573297 4.371899
21[15-30] 21.533770 45.891117 4.295620 4.198170
22[30-45] 37.047317 59.679583 3.927675 3.960149
23[45-60] 51.892241 74.951293 3.900810 4.004444
24[60-75] 66.828717 88.899354 4.207535 4.362599
25[75-90] 82.212025 102.702532 4.536062 4.788042
26[90-105] 97.385444 117.748979 5.149796 5.516673
27[105-120] 111.928729 132.076001 5.626556 6.024371
28[120-135] 126.822383 146.176534 5.613520 5.835964
29[135-150] 141.683526 162.210983 5.617823 5.780949
30[150-165] 157.483837 176.898332 6.887868 6.971621
31[165-180] 171.589352 188.888889 7.188426 7.194069
32[180-195] 187.002382 203.015485 5.355545 5.407082
33[195-210] 202.717400 219.100039 5.571109 5.657147
34[210-225] 218.342431 232.987274 7.196849 7.313788
35[225-240] 232.394529 247.631333 9.423809 9.594018
36[240-255] 247.634660 262.238499 9.388131 9.605217
37[255-270] 260.905513 277.101137 7.559757 7.802381
38[270-285] 276.039922 291.899464 5.941962 6.203880
39[285-300] 291.521139 306.436152 4.164875 4.377459
40[300-315] 307.145844 319.766446 3.795752 3.990653
41[315-330] 322.087945 332.487648 4.263681 4.391398
42[330-345] 337.370640 294.193944 5.160487 5.229559
43[345-360] 352.397252 34.222820 4.973387 4.941254
看见没,所有数据已经按照发生频率分组了,在任何的箱子中都是按照平局数来的。我们也可以按照最大值来分组: 01>>>grouped_max = grouped.max().reindex(new_index)
02Wind Dir 1 Wind Dir 2 Wind Speed 1 Wind Speed 2
03[0-15] 14 359 19.67 18.40
04[15-30] 29 358 13.87 13.40
05[30-45] 44 359 15.83 15.50
06[45-60] 59 359 16.48 16.59
07[60-75] 74 354 17.61 17.59
08[75-90] 89 354 17.06 17.20
09[90-105] 104 334 18.12 18.85
10[105-120] 119 352 16.98 17.27
11[120-135] 134 345 17.36 17.42
12[135-150] 149 329 20.71 20.46
13[150-165] 164 316 19.94 19.83
14[165-180] 179 359 19.67 19.31
15[180-195] 194 357 18.73 18.36
16[195-210] 209 358 19.18 19.04
17[210-225] 224 356 25.82 25.91
18[225-240] 239 359 29.64 29.73
19[240-255] 254 359 30.71 30.75
20[255-270] 269 358 26.15 26.31
21[270-285] 284 359 24.74 24.96
22[285-300] 299 355 18.28 18.46
23[300-315] 314 359 16.99 17.32
24[315-330] 329 359 16.68 17.05
25[330-345] 344 359 18.77 18.93
26[345-360] 359 359 18.74 18.47
哈哈哈哈,这就是Pandas的魔力啊!!!!!!!!!!!
如果觉得《实战 Pandas:分级和分组》对你有帮助,请点赞、收藏,并留下你的观点哦!