Python 重新格式化数据帧以匹配特定输出
我正在努力寻找一些Python 重新格式化数据帧以匹配特定输出,python,pandas,Python,Pandas,我正在努力寻找一些优雅的解决方案,从我的数据中获取我需要的东西。我能够得到我想要的,但是有太多的努力,我相信可以做得更好,这就是我想要的 下面是我的数据帧示例 >>> df = pd.DataFrame({'device_name': ['tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switc
优雅的解决方案,从我的数据中获取我需要的东西。我能够得到我想要的,但是有太多的努力,我相信可以做得更好,这就是我想要的
下面是我的数据帧示例
>>> df = pd.DataFrame({'device_name': ['tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1'], 'interface': ['ethernet3', 'ethernet4', 'ethernet38', 'ethernet7', 'ethernet8', 'ethernet31', 'ethernet1', 'ethernet12', 'ethernet20'], 'tap_port': ['1-tx-a-rx', '1-tx-b-rx', '1-b', '2-tx-a-rx', '2-tx-b-rx', '2-b', '3-tx-a-rx', '3-tx-b-rx', '3-b'], 'switch_name': ['sw_ag1', 'sw_ag1', 'sw_client1', 'sw_ag1', 'sw_ag1', 'sw_client2', 'sw_ag1', 'sw_ag1', 'sw_client3']})
当前数据帧形状:
我希望得到的理想输出是:
逻辑
因此,基本上我有一个网络设置,其中一个交换机用于连接多个接口。对于每个客户端交换机端口
有两个设备名称
接口-每个方向一个(RX/TX)。我正在使用tap\u port
name将所有这些组合成一个组,基于我看到的第一个整数,它表示“tap\u组”
当前的“解决方案”
我现在的做法是这样的,我不太清楚,也没有给我所需的输出
:
# Add new `id` column
>>> df['id']=df.tap_port.str[0]
# Get RX/TX direction as new column `direction`
>>> df['direction']=df.tap_port.apply(lambda x: x[-4:] if 'x' in x else '-')
# Trying to get the desired output
>>> df.pivot(index='id', columns='direction')[['switch_name','interface']]
switch_name interface
direction - a-rx b-rx - a-rx b-rx
id
1 sw_client1 sw_ag1 sw_ag1 ethernet38 ethernet3 ethernet4
2 sw_client2 sw_ag1 sw_ag1 ethernet31 ethernet7 ethernet8
3 sw_client3 sw_ag1 sw_ag1 ethernet20 ethernet1 ethernet12
这与我需要的非常接近,但不完全符合所需的输出
非常感谢您的帮助 我不认为这是一个最佳解决方案,但这是理想的输出
df = pd.DataFrame({'device_name': ['tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1'], 'interface': ['ethernet3', 'ethernet4', 'ethernet38', 'ethernet7', 'ethernet8', 'ethernet31', 'ethernet1', 'ethernet12', 'ethernet20'], 'tap_port': ['1-tx-a-rx', '1-tx-b-rx', '1-b', '2-tx-a-rx', '2-tx-b-rx', '2-b', '3-tx-a-rx', '3-tx-b-rx', '3-b'], 'switch_name': ['sw_ag1', 'sw_ag1', 'sw_client1', 'sw_ag1', 'sw_ag1', 'sw_client2', 'sw_ag1', 'sw_ag1', 'sw_client3']})
df['col']=pd.DataFrame([i.split('-') for i in df['tap_port']])[2].fillna('').replace({'a':'rx_int','b':'tx_int','':'client port'})
df['id']=[i.split('-')[0] for i in df['tap_port']]
df_pvt=df.pivot(index='id',columns='col',values='interface').reset_index()
x=df_pvt.join(df[['switch_name','device_name']][df['col']=='client port'].rename(columns={'switch_name':'client switch'}).reset_index(drop=True))
final=x.join(df[['switch_name']][df['col']=='tx_int'].rename(columns={'switch_name':'agg_switch'}).reset_index(drop=True))
Out[126]:
id client port rx_int tx_int client switch device_name agg_switch
0 1 ethernet38 ethernet3 ethernet4 sw_client1 tap_switch_1 sw_ag1
1 2 ethernet31 ethernet7 ethernet8 sw_client2 tap_switch_1 sw_ag1
2 3 ethernet20 ethernet1 ethernet12 sw_client3 tap_switch_1 sw_ag1
好吧,为了让这成为历史,这是我想出的解决方案。中途我意识到我可能有两个不同的agg_开关
变量,所以我不得不引入一个单独的列(agg_开关2
)
谢谢你的努力,非常感谢。让我们看看其他人是否会想出更好的办法。我的类似(但我使用的是pd.concat()),我没有在这里发布。@DanailPetrov好的:)我想我找到了一个更优雅/最优的解决方案。无论如何,谢谢你的回答!
# Add new `id` column
>>> df['id']=df.tap_port.str[0]
# Get RX/TX direction as new column `direction`
>>> df['direction']=df.tap_port.apply(lambda x: x[-4:] if 'x' in x else '-')
# Trying to get the desired output
>>> df.pivot(index='id', columns='direction')[['switch_name','interface']]
switch_name interface
direction - a-rx b-rx - a-rx b-rx
id
1 sw_client1 sw_ag1 sw_ag1 ethernet38 ethernet3 ethernet4
2 sw_client2 sw_ag1 sw_ag1 ethernet31 ethernet7 ethernet8
3 sw_client3 sw_ag1 sw_ag1 ethernet20 ethernet1 ethernet12
df = pd.DataFrame({'device_name': ['tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1', 'tap_switch_1'], 'interface': ['ethernet3', 'ethernet4', 'ethernet38', 'ethernet7', 'ethernet8', 'ethernet31', 'ethernet1', 'ethernet12', 'ethernet20'], 'tap_port': ['1-tx-a-rx', '1-tx-b-rx', '1-b', '2-tx-a-rx', '2-tx-b-rx', '2-b', '3-tx-a-rx', '3-tx-b-rx', '3-b'], 'switch_name': ['sw_ag1', 'sw_ag1', 'sw_client1', 'sw_ag1', 'sw_ag1', 'sw_client2', 'sw_ag1', 'sw_ag1', 'sw_client3']})
df['col']=pd.DataFrame([i.split('-') for i in df['tap_port']])[2].fillna('').replace({'a':'rx_int','b':'tx_int','':'client port'})
df['id']=[i.split('-')[0] for i in df['tap_port']]
df_pvt=df.pivot(index='id',columns='col',values='interface').reset_index()
x=df_pvt.join(df[['switch_name','device_name']][df['col']=='client port'].rename(columns={'switch_name':'client switch'}).reset_index(drop=True))
final=x.join(df[['switch_name']][df['col']=='tx_int'].rename(columns={'switch_name':'agg_switch'}).reset_index(drop=True))
Out[126]:
id client port rx_int tx_int client switch device_name agg_switch
0 1 ethernet38 ethernet3 ethernet4 sw_client1 tap_switch_1 sw_ag1
1 2 ethernet31 ethernet7 ethernet8 sw_client2 tap_switch_1 sw_ag1
2 3 ethernet20 ethernet1 ethernet12 sw_client3 tap_switch_1 sw_ag1
cols=['device_name','id','client_port','rx_int','tx_int','client_switch','agg_switch', 'agg_switch2']
>>> new_df=(df
... .set_index(['device_name','id','direction'])
... .unstack('direction')[['interface','switch_name']]
... .reset_index(col_level=-2)
... .droplevel(0, axis=1)
)
>>> new_df.columns = cols
>>> new_df
device_name id client_port rx_int tx_int client_switch agg_switch agg_switch2
0 tap_switch_1 1 ethernet38 ethernet3 ethernet4 sw_client1 sw_ag1 sw_ag1
1 tap_switch_1 2 ethernet31 ethernet7 ethernet8 sw_client2 sw_ag1 sw_ag1
2 tap_switch_1 3 ethernet20 ethernet1 ethernet12 sw_client3 sw_ag1 sw_ag1