如何用Pandas将服务器Oracle客户端表转为指定宽表格式?
解决Pandas Crosstab复合索引转普通列的问题
问题背景
我们有一张非规范化的服务器表,包含服务器主机名、IP(主机名与IP为一对一关系),以及安装在服务器上的多个Oracle客户端版本。原始数据构造及输出如下:
import pandas as pd from tabulate import tabulate col_server = ['server_A','server_A','server_A'] col_ip = ['ip_A' , 'ip_A' , 'ip_A' ] col_ora_client = ['11' ,'12' ,'19' ] df = pd.DataFrame(data=list(zip(col_server,col_ip,col_ora_client)) , columns=["server","ip","ora_client"]) print(tabulate(df, headers='keys', tablefmt='psql'))
运行输出:
+----+----------+------+--------------+ | | server | ip | ora_client | |----+----------+------+--------------| | 0 | server_A | ip_A | 11 | | 1 | server_A | ip_A | 12 | | 2 | server_A | ip_A | 19 | +----+----------+------+--------------+
期望格式
需要将数据转换为宽表,每个Oracle客户端版本作为独立列,存在则标记为1:
+----------+------+----+----+----+ | server | ip | 11 | 12 | 19 | +----------+------+----+----+----+ | server_A | ip_A | 1 | 1 | 1 | +----------+------+----+----+----+
尝试的问题
使用pd.crosstab透视后,server和ip以元组形式作为复合索引,不符合需求:
df_b = pd.crosstab([df['server'], df['ip']], df['ora_client']) print(tabulate(df_b, headers='keys', tablefmt='psql'))
输出:
+----------------------+------+------+------+ | | 11 | 12 | 19 | |----------------------+------+------+------| | ('server_A', 'ip_A') | 1 | 1 | 1 | +----------------------+------+------+------+
解决方案
方法1:用reset_index()还原索引列
在crosstab结果上调用reset_index(),将复合索引转为普通列,再通过tabulate参数隐藏默认索引:
df_b = pd.crosstab([df['server'], df['ip']], df['ora_client']).reset_index() print(tabulate(df_b, headers='keys', tablefmt='psql', showindex=False))
输出:
+----------+------+------+------+------+ | server | ip | 11 | 12 | 19 | +----------+------+------+------+------| | server_A | ip_A | 1 | 1 | 1 | +----------+------+------+------+------+
方法2:使用pivot_table替代crosstab
直接通过pivot_table指定行、列和统计逻辑,同样能得到目标格式:
df_b = df.pivot_table(index=['server', 'ip'], columns='ora_client', aggfunc='size', fill_value=0).reset_index() print(tabulate(df_b, headers='keys', tablefmt='psql', showindex=False))
输出结果与方法1完全一致。
内容的提问来源于stack exchange,提问作者glezo
相关产品推荐
相关产品推荐

