17. Pandas的Categorical Data相关函数
本章在前两章内容的理解之上研究一下和Categorical Data相关的一些函数和属性。
17.1 修改Categorical的categories
Categorical Data数据的categories是可以通过赋值或者rename函数被修替换改掉的。
- 通过赋值的方式改变categories或者用set_categories() 函数。
import pandas as pd
idx = [1,2,3,5,6,7,9,4,8]
name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
df['fruit'] = df['fruit'].astype('category')
print df,"\n"
print df.fruit.values.categories
print df.fruit.values.codes
df.fruit.values.categories = ["Pearl", "Orange", "Apple"]
print df.fruit.values.categories
print df.fruit.values.codes
print df
程序执行结果
fruit price
1 apple 5.2
2 pearl 3.5
3 orange 7.3
5 apple 5.0
6 orange 7.5
7 orange 7.3
9 apple 5.2
4 pearl 3.7
8 orange 7.3
Index([u'apple', u'orange', u'pearl'], dtype='object')
[0 2 1 0 1 1 0 2 1]
Index([u'Pearl', u'Orange', u'Apple'], dtype='object')
[0 2 1 0 1 1 0 2 1]
fruit price
1 Pearl 5.2
2 Apple 3.5
3 Orange 7.3
5 Pearl 5.0
6 Orange 7.5
7 Orange 7.3
9 Pearl 5.2
4 Apple 3.7
8 Orange 7.3
对比一下改变了categorical date的categories后数据的变化情况,这里categorical的codes并未改变,但最后的df.fruit的输出值values的值却发生了变化。
供货商 | 水果 | 价格 | 替换前后 | 水果 | 价格 |
---|---|---|---|---|---|
1 | apple | 5.20 | <==> | Pearl | 5.20 |
2 | pearl | 3.50 | <==> | Apple | 3.50 |
3 | orange | 7.30 | <==> | Orange | 7.30 |
5 | apple | 5.00 | <==> | Pearl | 5.00 |
6 | orange | 7.50 | <==> | Orange | 7.50 |
7 | orange | 7.30 | <==> | Orange | 7.30 |
9 | apple | 5.20 | <==> | Pearl | 5.20 |
4 | pearl | 3.70 | <==> | Apple | 3.70 |
8 | orange | 7.30 | <==> | Orange | 7.30 |
原因是原categorical data变量df.fruit的categories是["apple","orange","pearl" ]
被变成了["Pearl", "Orange", "Apple"]
,注意此函数有个参数inplace默认是False即不影响原数据,如果想影响原categorical data数据则需将inplace设置为True。
- 使用rename_categories函数来修改categories值。
import pandas as pd
idx = [1,2,3,5,6,7,9,4,8]
name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
df['fruit'] = df['fruit'].astype('category')
print df[:4],"\n"
print df.fruit.values.categories
print df.fruit.values.codes
df.fruit.values.rename_categories(["Pearl", "Orange", "Apple"],inplace = True)
print df.fruit.values.categories
print df.fruit.values.codes
print df[:4]
程序的执行结果:
fruit price
1 apple 5.2
2 pearl 3.5
3 orange 7.3
5 apple 5.0
Index([u'apple', u'orange', u'pearl'], dtype='object')
[0 2 1 0 1 1 0 2 1]
Index([u'Pearl', u'Orange', u'Apple'], dtype='object')
[0 2 1 0 1 1 0 2 1]
fruit price
1 Pearl 5.2
2 Apple 3.5
3 Orange 7.3
5 Pearl 5.0
17.2 增加categories
增加categories即增加分类个数,可以使用add_categories函数。下面给示例增加一个供应水果种类watermelon西瓜。
import pandas as pd
idx = [1,2,3,5,6,7,9,4,8]
name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
df['fruit'] = df['fruit'].astype('category')
df_new = pd.DataFrame({"fruit":["watermelon"] * 3,
"price":[2.75, 2.60, 2.55]},
index = [11, 12, 13])
df.fruit.values.add_categories("watermelon", inplace = True)
print "insert datas->\n",df_new
df = df.append(df_new)
print "after insert->\n", df
print "categories->\n",df.fruit.values.categories
print "codes->\n",df.fruit.values.codes
程序执行结果如下:
insert datas->
fruit price
11 watermelon 2.75
12 watermelon 2.60
13 watermelon 2.55
after insert->
fruit price
1 apple 5.20
2 pearl 3.50
3 orange 7.30
5 apple 5.00
6 orange 7.50
7 orange 7.30
9 apple 5.20
4 pearl 3.70
8 orange 7.30
11 watermelon 2.75
12 watermelon 2.60
13 watermelon 2.55
categories->
Index([u'apple', u'orange', u'pearl', u'watermelon'], dtype='object')
codes->
[0 2 1 0 1 1 0 2 1 3 3 3]
这里需要注意的是add_categories函数需要在插入数据之前调用,否则数据增加进去了但是codes并未更新都是-1。
如果将df.fruit.values.add_categories("watermelon", inplace = True)
放在添加数据语句df = df.append(df_new)
之后:
import pandas as pd
idx = [1,2,3,5,6,7,9,4,8]
name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
df['fruit'] = df['fruit'].astype('category')
df_new = pd.DataFrame({"fruit":["watermelon"] * 3,
"price":[2.75, 2.60, 2.55]},
index = [11, 12, 13])
print "insert datas->\n",df_new
df = df.append(df_new)
df.fruit.values.add_categories("watermelon", inplace = True)
print "after insert->\n", df
print "categories->\n",df.fruit.values.categories
print "codes->\n",df.fruit.values.codes
结果则是:
insert datas->
fruit price
11 watermelon 2.75
12 watermelon 2.60
13 watermelon 2.55
after insert->
fruit price
1 apple 5.20
2 pearl 3.50
3 orange 7.30
5 apple 5.00
6 orange 7.50
7 orange 7.30
9 apple 5.20
4 pearl 3.70
8 orange 7.30
11 NaN 2.75
12 NaN 2.60
13 NaN 2.55
categories->
Index([u'apple', u'orange', u'pearl', u'watermelon'], dtype='object')
codes->
[ 0 2 1 0 1 1 0 2 1 -1 -1 -1]
17.3 删除categories
如果水果点不卖苹果了apple那么fruit下得删除所有的apple记录,种类categories里也得去掉apple。
import pandas as pd
idx = [1,2,3,5,6,7,9,4,8]
name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
df['fruit'] = df['fruit'].astype('category')
print "before del 'apple'\n", df
df = df[df.fruit != "apple"]
df.fruit.values.remove_categories("apple", inplace = True)
print "after del 'apple'\n", df
print "categories->\n",df.fruit.values.categories
print "codes->\n",df.fruit.values.codes
print df.fruit
程序的执行结果:
before del 'apple'
fruit price
1 apple 5.2
2 pearl 3.5
3 orange 7.3
5 apple 5.0
6 orange 7.5
7 orange 7.3
9 apple 5.2
4 pearl 3.7
8 orange 7.3
after del 'apple'
fruit price
2 pearl 3.5
3 orange 7.3
6 orange 7.5
7 orange 7.3
4 pearl 3.7
8 orange 7.3
categories->
Index([u'orange', u'pearl'], dtype='object')
codes->
[1 0 0 0 1 0]
2 pearl
3 orange
6 orange
7 orange
4 pearl
8 orange
Name: fruit, dtype: category
Categories (2, object): [orange, pearl]
代码里df = df[df.fruit != "apple"]
是利用布尔选择删除了所有的"apple"的记录,而df.fruit.values.remove_categories("apple", inplace = True)
则是删除了df的fruit这个categorical data的categories里的种类"apple",如果注释掉此语句,codes则还是用原categories进行编码。
import pandas as pd
idx = [1,2,3,5,6,7,9,4,8]
name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
df['fruit'] = df['fruit'].astype('category')
print "before del 'apple'\n", df
df = df[df.fruit != "apple"]
#df.fruit.values.remove_categories("apple", inplace = True)
print "after del 'apple'\n", df
print "categories->\n",df.fruit.values.categories
print "codes->\n",df.fruit.values.codes
print df.fruit
结果为:
before del 'apple'
fruit price
1 apple 5.2
2 pearl 3.5
3 orange 7.3
5 apple 5.0
6 orange 7.5
7 orange 7.3
9 apple 5.2
4 pearl 3.7
8 orange 7.3
after del 'apple'
fruit price
2 pearl 3.5
3 orange 7.3
6 orange 7.5
7 orange 7.3
4 pearl 3.7
8 orange 7.3
categories->
Index([u'apple', u'orange', u'pearl'], dtype='object')
codes->
[2 1 1 1 2 1]
2 pearl
3 orange
6 orange
7 orange
4 pearl
8 orange
Name: fruit, dtype: category
Categories (3, object): [apple, orange, pearl]
删除了categories后的codes为[1 0 0 0 1 0]
,没执行删除categories的codes为[2 1 1 1 2 1]
。
17.4 删除未使用的categories
删除未使用的categories的意思是数据里没有那么的分类,那么可以将categories没有用到的categories删除。
import pandas as pd
cat = ["watermelon","pearl","orange", "apple"]
idx = [1,2,3,5,6,7,9,4,8]
name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
df['fruit'] = df['fruit'].astype('category')
print "1_initial-->"
print "dataframe:\n",df[:3]
print "categories:\n",df.fruit.values.categories
print "codes:\n",df.fruit.values.codes
df.fruit.cat.set_categories(cat, inplace = True)
print "\n2_after set_catgories()-->"
print "dataframe:\n",df[:3]
print "categories:\n",df.fruit.values.categories
print "codes:\n",df.fruit.values.codes
df.fruit.cat.remove_unused_categories(inplace = True)
print "\n3_after remove used categories-->"
print "categories:\n",df.fruit.values.categories
print "codes:\n",df.fruit.values.codes
print "dataframe:\n",df[:3]
程序的执行结果:
1_initial-->
dataframe:
fruit price
1 apple 5.2
2 pearl 3.5
3 orange 7.3
categories:
Index([u'apple', u'orange', u'pearl'], dtype='object')
codes:
[0 2 1 0 1 1 0 2 1]
2_after set_catgories()-->
dataframe:
fruit price
1 apple 5.2
2 pearl 3.5
3 orange 7.3
categories:
Index([u'watermelon', u'pearl', u'orange', u'apple'], dtype='object')
codes:
[3 1 2 3 2 2 3 1 2]
3_after remove used categories-->
categories:
Index([u'pearl', u'orange', u'apple'], dtype='object')
codes:
[2 0 1 2 1 1 2 0 1]
dataframe:
fruit price
1 apple 5.2
2 pearl 3.5
3 orange 7.3
从程序的执行结果可以看出,数据并未发生变化,变化的只是数据的categories。df['fruit'] = df['fruit'].astype('category')
设置fruit列为categorical data型数据,创建了其categories为['pearl', 'orange', 'apple']
;语句df.fruit.cat.set_categories(cat, inplace = True)
改变了其categories为['watermelon', 'pearl', 'orange', 'apple']
;而语句df.fruit.cat.remove_unused_categories(inplace = True)
删除了尚未使用的watermelon分类回到了['pearl', 'orange', 'apple']
。
17.5 value_counts函数
value_counts函数可以统计categorical data的各个categories数据出现的次数,算式categorical data的一种典型应用。
import pandas as pd
cat = ["watermelon","pearl","orange", "apple"]
idx = [1,2,3,5,6,7,9,4,8]
name = ["apple","pearl","orange", "apple","orange","orange","apple","pearl","orange"]
price = [5.20,3.50,7.30,5.00,7.50,7.30,5.20,3.70,7.30]
df = pd.DataFrame({ "fruit": name , "price" : price}, index = idx)
df['fruit'] = df['fruit'].astype('category')
print "dataframe:\n",df
print "categories:\n",df.fruit.values.categories
print "codes:\n",df.fruit.values.codes
print "value_counts()\n", df.fruit.value_counts()
程序的执行结果:
dataframe:
fruit price
1 apple 5.2
2 pearl 3.5
3 orange 7.3
5 apple 5.0
6 orange 7.5
7 orange 7.3
9 apple 5.2
4 pearl 3.7
8 orange 7.3
categories:
Index([u'apple', u'orange', u'pearl'], dtype='object')
codes:
[0 2 1 0 1 1 0 2 1]
value_counts()
orange 4
apple 3
pearl 2
dtype: int64
感谢Klang(金浪)智能数据看板klang.org.cn鼎力支持!