最近在学习《Python数据分析与挖掘实战》中的案例,写写自己的心得。
代码分为两大部分:1.读取数据并进行聚类分析
2.应用Apriori关联规则挖掘规律
1.聚类部分函数分析:
def programmer_1():
datafile = "C:/Users/longming/Desktop/chapter8/data/data.xls"
processedfile = "C:/Users/longming/Desktop/chapter8/tmp/data_processed.xls"
typelabel = {
u"肝气郁结证型系数": "A",
u"热毒蕴结证型系数": "B",
u"冲任失调证型系数": "C",
u"气血两虚证型系数": "D",
u"脾胃虚弱证型系数": "E",
u"肝肾阴虚证型系数": "F",
}
k = 4#聚类数目
data = pd.read_excel(datafile)
result = pd.DataFrame()
#创建空数据帧
#print(typelabel.items()) 测试.items()方法,返回以元组为元素的列表
for key, item in typelabel.items():
print(u"正在进行“%s”的聚类..." % key)
# 进行聚类离散化
kmodel = KMeans(n_clusters=k, n_jobs=4)
print(data['key'])
kmodel.fit(data[[key]].as_matrix())
#转换为numpy数组.as_matrix()
# 聚类中心
r1 = pd.DataFrame(kmodel.cluster_centers_, columns=[item])
# 分类统计
r2 = pd.Series(kmodel.labels_).value_counts()
r2 = pd.DataFrame(r2, columns=[item + "n"])
# 合并为一个DataFrame
r = pd.concat([r1, r2], axis=1).sort_values(item)
r.index = list(range(1, 5))#设置行标签
# 用来计算相邻两列的均值,以此作为边界点
r[item] = pd.Series.rolling(r[item], 2).mean()
# 将NaN值转为0.0,不用fillna的原因是数值类型是float64
r.loc[1, item] = 0.0
result = result.append(r.T)
# 以ABCDEF排序
result = result.sort_index()
result.to_excel(processedfile)
其中24行的data[[key]].as_matrix(),df[['列名']]属于按列读取。
.as_matrix()保存为numpy数组。
2.Apriori关联规则算法
# 自定义连接函数
def connect_string(x, ms):
x = list(map(lambda i: sorted(i.split(ms)), x))
r = []
for i in range(len(x)):
for j in range(i + 1, len(x)):
if x[i][:-1] == x[j][:-1] and x[i][-1] != x[j][-1]:
r.append(x[i][:-1] + sorted([x[j][-1], x[i][-1]]))#长度+1
#print(r)
return r
# 寻找关联规则函数
def find_rule(d, support, confidence, ms=u"--"):
result = pd.DataFrame(index=["support", "confidence"])
print(result)
# 第一批支持度筛选
support_series = 1.0 * d.sum() / len(d)
#dataframe.sum()返回一个含有列小计的Series,axis=0代表对列进行求和
#调用DataFrame的sum方法将会返回一个含有列小计的Series:传入axis=1将会按行进行求和运算
#print(support_series)
#逐行计算
column = list(support_series[support_series > support].index)
#attribute:.index属于series,查找series的标签
#print(column)
k = 0
while len(column) > 1:
k = k + 1
print(u"\n正在进行第%s次搜索..." % k)
column = connect_string(column, ms)
#print(column) 返回频繁项组合
print(u"数目%s..." % len(column))
index_lst = [ms.join(i) for i in column]
#print(index_lst)
# 新的支持度函数 .prod(axis=1)返回行方向乘积
sf = lambda i: d[i].prod(axis=1, numeric_only=True)
# 计算连接后的支持度,开始筛选
d_2 = pd.DataFrame(list(map(sf, column)), index=index_lst).T
#print(d_2)
support_series_2 = 1.0 * d_2[index_lst].sum() / len(d)
#print(support_series_2)
column = list(support_series_2[support_series_2 > support].index)
#print(column)
support_series = support_series.append(support_series_2)
# print(support_series)
column2 = []
# 遍历所有可能的情况
for i in column:
i = i.split(ms)
for j in range(len(i)):
column2.append(i[:j] + i[j + 1:] + i[j:j + 1])
#将column中的标签排列出更多组合
#print(column2)
# 置信度序列
cofidence_series = pd.Series(index=[ms.join(i) for i in column2])
for i in column2:
cofidence_series[ms.join(i)] = support_series[ms.join(
sorted(i))] / support_series[ms.join(i[:-1])]
#print(cofidence_series)
# 置信度筛选
for i in cofidence_series[cofidence_series > confidence].index:
result[i] = 0.0
result[i]["confidence"] = cofidence_series[i]
result[i]["support"] = support_series[ms.join(sorted(i.split(ms)))]
#join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。
print(result)
result = result.T.sort_values(["confidence", "support"], ascending=False)
#.sort_values 按任意轴的值进行排序,ascending=False降序
print(u"\nresult:")
print(result)
return result
def programmer_2():
inputfile = "D:\Dream_way\python_data_analysis_and_mining_action-master\chapter8\data/apriori.txt"
data = pd.read_csv(inputfile, header=None, dtype=object)
#print(data)
# 计时
start = time.clock()
print(u"\n转换原始数据至0-1矩阵...")
# 0-1矩阵的转换
ct = lambda x: pd.Series(1, index=x[pd.notnull(x)])
b = list(map(ct, data.as_matrix()))
#生成1维series,map()映射函数到特定对象
#print(b)
""" a = pd.DataFrame(b)
print(a) """
data = pd.DataFrame(b).fillna(0)
#print(data)
end = time.clock()
print(u"\n转换完毕,用时:%0.2f s" % (end - start))
# 删除中间变量b,节省内存
del b
# 定义支持度,置信度,连接符号
support = 0.06
confidence = 0.75
ms = "---"
# 计时
start = time.clock()
print(u"\n开始搜索关联规则...")
find_rule(data, support, confidence, ms)
end = time.clock()
print(u"\n搜索完成,用时%0.2f s" % (end - start))
一点理解:
data = pd.DataFrame(b).fillna(0)
将一维Series转换成Dataframe,Nan值用 .fillna(0)方法填充
data此时结构如下所示:
A2 B1 C3 D3 E1 F1 H1 B2 A1 C1 D1 E2 H2 A3 D2 E3 C2 H3 B4 E4 H4 D4 A4 B3 F2 C4 F3 F4
0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
3 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
support_series = 1.0 * d.sum() / len(d)
这里的d是Dataframe格式,对于这种格式, .sum()返回一维Series格式。
3.Apriori算法解析
参考:1.https://wizardforcel.gitbooks.io/dm-algo-top10/content/apriori.html
建议参考第二个理解原理。