{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Pandas Examples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Batfish questions can return a huge amount of data, which you may want to filter in various ways based on your task. While most Batfish questions support basic filtering, they may not support your desired filtering criteria. Further, for performance, you may want to fetch the answer once and filter it using multiple different criteria. These scenarios are where Pandas-based filtering can help. \n", "\n", "Batfish answers can be easily turned into a [Pandas DataFrame](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html) (using `.frame()`), after which you can use the full power of Pandas to filter and manipulate data. This notebook provides a few examples of common manipulations for Batfish. It is not intended as a complete guide of Pandas data manipulation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's first initialize a snapshot that we will use in our examples." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'snapshot'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Import packages\n", "%run startup.py\n", "bf = Session(host=\"localhost\")\n", "\n", "# Initialize a network and a snapshot\n", "bf.set_network(\"pandas-example\")\n", "\n", "SNAPSHOT_NAME = \"snapshot\"\n", "SNAPSHOT_PATH = \"networks/hybrid-cloud/\"\n", "bf.init_snapshot(SNAPSHOT_PATH, name=SNAPSHOT_NAME, overwrite=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Filtering `initIssues`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After initializing the snapshot, you often want to look at the [initIssues](https://pybatfish.readthedocs.io/en/latest/notebooks/snapshot.html#Snapshot-Initialization-Issues) answer. If there are too many issues, you may want to ignore a particular class of issues. We show below how to do that. " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NodesSource_LinesTypeDetailsLine_TextParser_Context
0['leaf1']NoneConvert warning (redflag)Interface Ethernet12 has an undefined channel group Port-Channel20NoneNone
1None[configs/Leaf1.cfg:[6], configs/Leaf2.cfg:[6], configs/Leaf3.cfg:[6], configs/Leaf4.cfg:[6], configs/Spine1.cfg:[6], configs/Spine2.cfg:[6]]Parse warningThis syntax is unrecognizedtransceiver qsfp default-mode 4x10G[arista_configuration]
2None[aws_configs:[]]Parse warning (unimplemented)Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-west-2/VpcEndpointServices.jsonNoneNone
3None[aws_configs:[]]Parse warning (unimplemented)Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-east-2/VpcEndpointServices.jsonNoneNone
\n", "
" ], "text/plain": [ " Nodes \\\n", "0 ['leaf1'] \n", "1 None \n", "2 None \n", "3 None \n", "\n", " Source_Lines \\\n", "0 None \n", "1 [configs/Leaf1.cfg:[6], configs/Leaf2.cfg:[6], configs/Leaf3.cfg:[6], configs/Leaf4.cfg:[6], configs/Spine1.cfg:[6], configs/Spine2.cfg:[6]] \n", "2 [aws_configs:[]] \n", "3 [aws_configs:[]] \n", "\n", " Type \\\n", "0 Convert warning (redflag) \n", "1 Parse warning \n", "2 Parse warning (unimplemented) \n", "3 Parse warning (unimplemented) \n", "\n", " Details \\\n", "0 Interface Ethernet12 has an undefined channel group Port-Channel20 \n", "1 This syntax is unrecognized \n", "2 Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-west-2/VpcEndpointServices.json \n", "3 Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-east-2/VpcEndpointServices.json \n", "\n", " Line_Text Parser_Context \n", "0 None None \n", "1 transceiver qsfp default-mode 4x10G [arista_configuration] \n", "2 None None \n", "3 None None " ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Lets get the initIssues for our snapshot\n", "issues = bf.q.initIssues().answer().frame()\n", "issues" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NodesSource_LinesTypeDetailsLine_TextParser_Context
0['leaf1']NoneConvert warning (redflag)Interface Ethernet12 has an undefined channel group Port-Channel20NoneNone
2None[aws_configs:[]]Parse warning (unimplemented)Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-west-2/VpcEndpointServices.jsonNoneNone
3None[aws_configs:[]]Parse warning (unimplemented)Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-east-2/VpcEndpointServices.jsonNoneNone
\n", "
" ], "text/plain": [ " Nodes Source_Lines Type \\\n", "0 ['leaf1'] None Convert warning (redflag) \n", "2 None [aws_configs:[]] Parse warning (unimplemented) \n", "3 None [aws_configs:[]] Parse warning (unimplemented) \n", "\n", " Details \\\n", "0 Interface Ethernet12 has an undefined channel group Port-Channel20 \n", "2 Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-west-2/VpcEndpointServices.json \n", "3 Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-east-2/VpcEndpointServices.json \n", "\n", " Line_Text Parser_Context \n", "0 None None \n", "2 None None \n", "3 None None " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ignore all issues whose Line_Text contain one of these as a substring\n", "line_texts_to_ignore = [\"transceiver\"]\n", "\n", "\n", "def has_substring(text: Optional[str], substrings: List[str]) -> bool:\n", " \"\"\"Returns True if 'text' is not None and contains one of the 'substrings'\"\"\"\n", " return text is not None and any(substr in text for substr in substrings)\n", "\n", "\n", "issues[\n", " issues.apply(\n", " lambda issue: not has_substring(issue[\"Line_Text\"], line_texts_to_ignore),\n", " axis=1,\n", " )\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the code above, we are using the Pandas method [apply](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.apply.html) to map `issues` to a binary array based on whether the issue has one of the substrings in `line_texts_to_ignore`. Passing `axis=1` makes `apply` iterate over rows instead of columns. The helper method `has_substring` makes this determination. It returns `True` if `text` is not `None` and has any of the substrings. The Python method [any](https://docs.python.org/3/library/functions.html#any) returns `True` if any element of the input iterable is `True`. Using the binary array as a filter for `issues` produces rows that match our criterion. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Instead of ignoring some issues, you may want to focus on issues that match a certain criteria. That too can be easily accomplished, as follows." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NodesSource_LinesTypeDetailsLine_TextParser_Context
2None[aws_configs:[]]Parse warning (unimplemented)Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-west-2/VpcEndpointServices.jsonNoneNone
3None[aws_configs:[]]Parse warning (unimplemented)Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-east-2/VpcEndpointServices.jsonNoneNone
\n", "
" ], "text/plain": [ " Nodes Source_Lines Type \\\n", "2 None [aws_configs:[]] Parse warning (unimplemented) \n", "3 None [aws_configs:[]] Parse warning (unimplemented) \n", "\n", " Details \\\n", "2 Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-west-2/VpcEndpointServices.json \n", "3 Unrecognized element 'ServiceDetails' in AWS file aws_configs/us-east-2/VpcEndpointServices.json \n", "\n", " Line_Text Parser_Context \n", "2 None None \n", "3 None None " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Only show issues whose details match these substrings\n", "focus_details = [\"Unrecognized element 'ServiceDetails' in AWS\"]\n", "\n", "issues[\n", " issues.apply(lambda issue: has_substring(issue[\"Details\"], focus_details), axis=1)\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The code above is similar to the one we used earlier, with the only differences being that we use the `focus_details` list as the argument to the `has_substrings` helper and we do not invert its result." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Filtering objects" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "`Line_Text` and `Details` columns above have string values, but many Batfish answers contain other data types as well. We generalize the approach above to filter other data types and to filter based on multiple columns. We use the `interfaceProperties` question for this demonstrate." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
InterfaceAccess_VLANActiveAdmin_UpAll_PrefixesAllowed_VLANsAuto_State_VLANBandwidthBlacklistedChannel_GroupChannel_Group_MembersDHCP_Relay_AddressesDeclared_NamesDescriptionEncapsulation_VLANHSRP_GroupsHSRP_VersionInactive_ReasonIncoming_Filter_NameMLAG_IDMTUNative_VLANOutgoing_Filter_NamePBR_Policy_NamePrimary_AddressPrimary_NetworkProxy_ARPRip_EnabledRip_PassiveSpanning_Tree_PortfastSpeedSwitchportSwitchport_ModeSwitchport_Trunk_EncapsulationVRFVRRP_GroupsZone_Name
0__aws-services-gateway__[aws-services]NoneTrueTrue[]True1000000000000.0FalseNone[][][]To AWS servicesNone[]NoneNoneNone1500NoneNoneNonelink-local:169.254.0.1NoneFalseFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
1__aws-services-gateway__[backbone]NoneTrueTrue[]True1000000000000.0FalseNone[][][]To AWS backboneNone[]NoneNoneNone1500NoneNoneNonelink-local:169.254.0.1NoneFalseFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
2exitgw[GigabitEthernet1]NoneTrueTrue['10.10.100.2/24']True1000000000.0FalseNone[][]['GigabitEthernet1']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.100.2/2410.10.100.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
3exitgw[GigabitEthernet2]NoneTrueTrue['10.10.101.2/24']True1000000000.0FalseNone[][]['GigabitEthernet2']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.101.2/2410.10.101.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
4exitgw[GigabitEthernet3]NoneTrueTrue['147.75.69.27/31']True1000000000.0FalseNone[][]['GigabitEthernet3']NoneNone[]NoneNoneNone1500NoneNoneNone147.75.69.27/31147.75.69.26/31TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
\n", "
" ], "text/plain": [ " Interface Access_VLAN Active Admin_Up \\\n", "0 __aws-services-gateway__[aws-services] None True True \n", "1 __aws-services-gateway__[backbone] None True True \n", "2 exitgw[GigabitEthernet1] None True True \n", "3 exitgw[GigabitEthernet2] None True True \n", "4 exitgw[GigabitEthernet3] None True True \n", "\n", " All_Prefixes Allowed_VLANs Auto_State_VLAN Bandwidth \\\n", "0 [] True 1000000000000.0 \n", "1 [] True 1000000000000.0 \n", "2 ['10.10.100.2/24'] True 1000000000.0 \n", "3 ['10.10.101.2/24'] True 1000000000.0 \n", "4 ['147.75.69.27/31'] True 1000000000.0 \n", "\n", " Blacklisted Channel_Group Channel_Group_Members DHCP_Relay_Addresses \\\n", "0 False None [] [] \n", "1 False None [] [] \n", "2 False None [] [] \n", "3 False None [] [] \n", "4 False None [] [] \n", "\n", " Declared_Names Description Encapsulation_VLAN HSRP_Groups \\\n", "0 [] To AWS services None [] \n", "1 [] To AWS backbone None [] \n", "2 ['GigabitEthernet1'] None None [] \n", "3 ['GigabitEthernet2'] None None [] \n", "4 ['GigabitEthernet3'] None None [] \n", "\n", " HSRP_Version Inactive_Reason Incoming_Filter_Name MLAG_ID MTU Native_VLAN \\\n", "0 None None None 1500 None \n", "1 None None None 1500 None \n", "2 None None None 1500 None \n", "3 None None None 1500 None \n", "4 None None None 1500 None \n", "\n", " Outgoing_Filter_Name PBR_Policy_Name Primary_Address \\\n", "0 None None link-local:169.254.0.1 \n", "1 None None link-local:169.254.0.1 \n", "2 None None 10.10.100.2/24 \n", "3 None None 10.10.101.2/24 \n", "4 None None 147.75.69.27/31 \n", "\n", " Primary_Network Proxy_ARP Rip_Enabled Rip_Passive Spanning_Tree_Portfast \\\n", "0 None False False False False \n", "1 None False False False False \n", "2 10.10.100.0/24 True False False False \n", "3 10.10.101.0/24 True False False False \n", "4 147.75.69.26/31 True False False False \n", "\n", " Speed Switchport Switchport_Mode Switchport_Trunk_Encapsulation \\\n", "0 None False NONE DOT1Q \n", "1 None False NONE DOT1Q \n", "2 1000000000.0 False NONE DOT1Q \n", "3 1000000000.0 False NONE DOT1Q \n", "4 1000000000.0 False NONE DOT1Q \n", "\n", " VRF VRRP_Groups Zone_Name \n", "0 default [] None \n", "1 default [] None \n", "2 default [] None \n", "3 default [] None \n", "4 default [] None " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Fetch interface properties and display its first five rows\n", "interfaces = bf.q.interfaceProperties().answer().frame()\n", "interfaces.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To filter based on a column, we need to know its data type. We can learn that in the [Batfish documentation](https://pybatfish.readthedocs.io/en/latest/questions.html) or by inspecting the answer we got from Batfish (e.g., using Python's `type()` method)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We show three examples of filtering based on the `Interface` and `Active` columns, which are of type [pybatfish.datamodel.primitives.Interface](https://pybatfish.readthedocs.io/en/latest/datamodel.html#pybatfish.datamodel.primitives.Interface) and `bool`, respectively. The former has `hostname` and `interface` properties (which are strings). " ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
InterfaceAccess_VLANActiveAdmin_UpAll_PrefixesAllowed_VLANsAuto_State_VLANBandwidthBlacklistedChannel_GroupChannel_Group_MembersDHCP_Relay_AddressesDeclared_NamesDescriptionEncapsulation_VLANHSRP_GroupsHSRP_VersionInactive_ReasonIncoming_Filter_NameMLAG_IDMTUNative_VLANOutgoing_Filter_NamePBR_Policy_NamePrimary_AddressPrimary_NetworkProxy_ARPRip_EnabledRip_PassiveSpanning_Tree_PortfastSpeedSwitchportSwitchport_ModeSwitchport_Trunk_EncapsulationVRFVRRP_GroupsZone_Name
2exitgw[GigabitEthernet1]NoneTrueTrue['10.10.100.2/24']True1000000000.0FalseNone[][]['GigabitEthernet1']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.100.2/2410.10.100.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
3exitgw[GigabitEthernet2]NoneTrueTrue['10.10.101.2/24']True1000000000.0FalseNone[][]['GigabitEthernet2']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.101.2/2410.10.101.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
4exitgw[GigabitEthernet3]NoneTrueTrue['147.75.69.27/31']True1000000000.0FalseNone[][]['GigabitEthernet3']NoneNone[]NoneNoneNone1500NoneNoneNone147.75.69.27/31147.75.69.26/31TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
5exitgw[GigabitEthernet4]NoneFalseFalse[]True1000000000.0FalseNone[][]['GigabitEthernet4']NoneNone[]NoneAdministratively downNoneNone1500NoneNoneNoneNoneNoneTrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
6exitgw[Loopback0]NoneTrueTrue['2.2.2.2/32']True8000000000.0NoneNone[][]['Loopback0']NoneNone[]NoneNoneNone1500NoneNoneNone2.2.2.2/322.2.2.2/32TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
7exitgw[Loopback123]NoneTrueTrue['192.168.123.7/32']True8000000000.0NoneNone[][]['Loopback123']NoneNone[]NoneNoneNone1500NoneNoneNone192.168.123.7/32192.168.123.7/32TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
8exitgw[Tunnel1]NoneTrueTrue['169.254.25.162/30']True100000.0NoneNone[][]['Tunnel1']NoneNone[]NoneNoneNone1500NoneNoneNone169.254.25.162/30169.254.25.160/30TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
9exitgw[Tunnel2]NoneTrueTrue['169.254.172.2/30']True100000.0NoneNone[][]['Tunnel2']NoneNone[]NoneNoneNone1500NoneNoneNone169.254.172.2/30169.254.172.0/30TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
10exitgw[Tunnel3]NoneTrueTrue['169.254.252.78/30']True100000.0NoneNone[][]['Tunnel3']NoneNone[]NoneNoneNone1500NoneNoneNone169.254.252.78/30169.254.252.76/30TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
11exitgw[Tunnel4]NoneTrueTrue['169.254.215.82/30']True100000.0NoneNone[][]['Tunnel4']NoneNone[]NoneNoneNone1500NoneNoneNone169.254.215.82/30169.254.215.80/30TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
\n", "
" ], "text/plain": [ " Interface Access_VLAN Active Admin_Up \\\n", "2 exitgw[GigabitEthernet1] None True True \n", "3 exitgw[GigabitEthernet2] None True True \n", "4 exitgw[GigabitEthernet3] None True True \n", "5 exitgw[GigabitEthernet4] None False False \n", "6 exitgw[Loopback0] None True True \n", "7 exitgw[Loopback123] None True True \n", "8 exitgw[Tunnel1] None True True \n", "9 exitgw[Tunnel2] None True True \n", "10 exitgw[Tunnel3] None True True \n", "11 exitgw[Tunnel4] None True True \n", "\n", " All_Prefixes Allowed_VLANs Auto_State_VLAN Bandwidth \\\n", "2 ['10.10.100.2/24'] True 1000000000.0 \n", "3 ['10.10.101.2/24'] True 1000000000.0 \n", "4 ['147.75.69.27/31'] True 1000000000.0 \n", "5 [] True 1000000000.0 \n", "6 ['2.2.2.2/32'] True 8000000000.0 \n", "7 ['192.168.123.7/32'] True 8000000000.0 \n", "8 ['169.254.25.162/30'] True 100000.0 \n", "9 ['169.254.172.2/30'] True 100000.0 \n", "10 ['169.254.252.78/30'] True 100000.0 \n", "11 ['169.254.215.82/30'] True 100000.0 \n", "\n", " Blacklisted Channel_Group Channel_Group_Members DHCP_Relay_Addresses \\\n", "2 False None [] [] \n", "3 False None [] [] \n", "4 False None [] [] \n", "5 False None [] [] \n", "6 None None [] [] \n", "7 None None [] [] \n", "8 None None [] [] \n", "9 None None [] [] \n", "10 None None [] [] \n", "11 None None [] [] \n", "\n", " Declared_Names Description Encapsulation_VLAN HSRP_Groups \\\n", "2 ['GigabitEthernet1'] None None [] \n", "3 ['GigabitEthernet2'] None None [] \n", "4 ['GigabitEthernet3'] None None [] \n", "5 ['GigabitEthernet4'] None None [] \n", "6 ['Loopback0'] None None [] \n", "7 ['Loopback123'] None None [] \n", "8 ['Tunnel1'] None None [] \n", "9 ['Tunnel2'] None None [] \n", "10 ['Tunnel3'] None None [] \n", "11 ['Tunnel4'] None None [] \n", "\n", " HSRP_Version Inactive_Reason Incoming_Filter_Name MLAG_ID MTU \\\n", "2 None None None 1500 \n", "3 None None None 1500 \n", "4 None None None 1500 \n", "5 None Administratively down None None 1500 \n", "6 None None None 1500 \n", "7 None None None 1500 \n", "8 None None None 1500 \n", "9 None None None 1500 \n", "10 None None None 1500 \n", "11 None None None 1500 \n", "\n", " Native_VLAN Outgoing_Filter_Name PBR_Policy_Name Primary_Address \\\n", "2 None None None 10.10.100.2/24 \n", "3 None None None 10.10.101.2/24 \n", "4 None None None 147.75.69.27/31 \n", "5 None None None None \n", "6 None None None 2.2.2.2/32 \n", "7 None None None 192.168.123.7/32 \n", "8 None None None 169.254.25.162/30 \n", "9 None None None 169.254.172.2/30 \n", "10 None None None 169.254.252.78/30 \n", "11 None None None 169.254.215.82/30 \n", "\n", " Primary_Network Proxy_ARP Rip_Enabled Rip_Passive \\\n", "2 10.10.100.0/24 True False False \n", "3 10.10.101.0/24 True False False \n", "4 147.75.69.26/31 True False False \n", "5 None True False False \n", "6 2.2.2.2/32 True False False \n", "7 192.168.123.7/32 True False False \n", "8 169.254.25.160/30 True False False \n", "9 169.254.172.0/30 True False False \n", "10 169.254.252.76/30 True False False \n", "11 169.254.215.80/30 True False False \n", "\n", " Spanning_Tree_Portfast Speed Switchport Switchport_Mode \\\n", "2 False 1000000000.0 False NONE \n", "3 False 1000000000.0 False NONE \n", "4 False 1000000000.0 False NONE \n", "5 False 1000000000.0 False NONE \n", "6 False None False NONE \n", "7 False None False NONE \n", "8 False None False NONE \n", "9 False None False NONE \n", "10 False None False NONE \n", "11 False None False NONE \n", "\n", " Switchport_Trunk_Encapsulation VRF VRRP_Groups Zone_Name \n", "2 DOT1Q default [] None \n", "3 DOT1Q default [] None \n", "4 DOT1Q default [] None \n", "5 DOT1Q default [] None \n", "6 DOT1Q default [] None \n", "7 DOT1Q default [] None \n", "8 DOT1Q default [] None \n", "9 DOT1Q default [] None \n", "10 DOT1Q default [] None \n", "11 DOT1Q default [] None " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Display all interfaces on node 'exitgw'\n", "interfaces[interfaces.apply(lambda row: row[\"Interface\"].hostname == \"exitgw\", axis=1)]" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
InterfaceAccess_VLANActiveAdmin_UpAll_PrefixesAllowed_VLANsAuto_State_VLANBandwidthBlacklistedChannel_GroupChannel_Group_MembersDHCP_Relay_AddressesDeclared_NamesDescriptionEncapsulation_VLANHSRP_GroupsHSRP_VersionInactive_ReasonIncoming_Filter_NameMLAG_IDMTUNative_VLANOutgoing_Filter_NamePBR_Policy_NamePrimary_AddressPrimary_NetworkProxy_ARPRip_EnabledRip_PassiveSpanning_Tree_PortfastSpeedSwitchportSwitchport_ModeSwitchport_Trunk_EncapsulationVRFVRRP_GroupsZone_Name
2exitgw[GigabitEthernet1]NoneTrueTrue['10.10.100.2/24']True1000000000.0FalseNone[][]['GigabitEthernet1']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.100.2/2410.10.100.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
3exitgw[GigabitEthernet2]NoneTrueTrue['10.10.101.2/24']True1000000000.0FalseNone[][]['GigabitEthernet2']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.101.2/2410.10.101.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
4exitgw[GigabitEthernet3]NoneTrueTrue['147.75.69.27/31']True1000000000.0FalseNone[][]['GigabitEthernet3']NoneNone[]NoneNoneNone1500NoneNoneNone147.75.69.27/31147.75.69.26/31TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
5exitgw[GigabitEthernet4]NoneFalseFalse[]True1000000000.0FalseNone[][]['GigabitEthernet4']NoneNone[]NoneAdministratively downNoneNone1500NoneNoneNoneNoneNoneTrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
\n", "
" ], "text/plain": [ " Interface Access_VLAN Active Admin_Up All_Prefixes \\\n", "2 exitgw[GigabitEthernet1] None True True ['10.10.100.2/24'] \n", "3 exitgw[GigabitEthernet2] None True True ['10.10.101.2/24'] \n", "4 exitgw[GigabitEthernet3] None True True ['147.75.69.27/31'] \n", "5 exitgw[GigabitEthernet4] None False False [] \n", "\n", " Allowed_VLANs Auto_State_VLAN Bandwidth Blacklisted Channel_Group \\\n", "2 True 1000000000.0 False None \n", "3 True 1000000000.0 False None \n", "4 True 1000000000.0 False None \n", "5 True 1000000000.0 False None \n", "\n", " Channel_Group_Members DHCP_Relay_Addresses Declared_Names \\\n", "2 [] [] ['GigabitEthernet1'] \n", "3 [] [] ['GigabitEthernet2'] \n", "4 [] [] ['GigabitEthernet3'] \n", "5 [] [] ['GigabitEthernet4'] \n", "\n", " Description Encapsulation_VLAN HSRP_Groups HSRP_Version \\\n", "2 None None [] None \n", "3 None None [] None \n", "4 None None [] None \n", "5 None None [] None \n", "\n", " Inactive_Reason Incoming_Filter_Name MLAG_ID MTU Native_VLAN \\\n", "2 None None 1500 None \n", "3 None None 1500 None \n", "4 None None 1500 None \n", "5 Administratively down None None 1500 None \n", "\n", " Outgoing_Filter_Name PBR_Policy_Name Primary_Address Primary_Network \\\n", "2 None None 10.10.100.2/24 10.10.100.0/24 \n", "3 None None 10.10.101.2/24 10.10.101.0/24 \n", "4 None None 147.75.69.27/31 147.75.69.26/31 \n", "5 None None None None \n", "\n", " Proxy_ARP Rip_Enabled Rip_Passive Spanning_Tree_Portfast Speed \\\n", "2 True False False False 1000000000.0 \n", "3 True False False False 1000000000.0 \n", "4 True False False False 1000000000.0 \n", "5 True False False False 1000000000.0 \n", "\n", " Switchport Switchport_Mode Switchport_Trunk_Encapsulation VRF \\\n", "2 False NONE DOT1Q default \n", "3 False NONE DOT1Q default \n", "4 False NONE DOT1Q default \n", "5 False NONE DOT1Q default \n", "\n", " VRRP_Groups Zone_Name \n", "2 [] None \n", "3 [] None \n", "4 [] None \n", "5 [] None " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Display all GigabitEthernet interfaces on node 'exitgw'\n", "interfaces[\n", " interfaces.apply(\n", " lambda row: row[\"Interface\"].hostname == \"exitgw\"\n", " and row[\"Interface\"].interface.startswith(\"GigabitEthernet\"),\n", " axis=1,\n", " )\n", "]" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
InterfaceAccess_VLANActiveAdmin_UpAll_PrefixesAllowed_VLANsAuto_State_VLANBandwidthBlacklistedChannel_GroupChannel_Group_MembersDHCP_Relay_AddressesDeclared_NamesDescriptionEncapsulation_VLANHSRP_GroupsHSRP_VersionInactive_ReasonIncoming_Filter_NameMLAG_IDMTUNative_VLANOutgoing_Filter_NamePBR_Policy_NamePrimary_AddressPrimary_NetworkProxy_ARPRip_EnabledRip_PassiveSpanning_Tree_PortfastSpeedSwitchportSwitchport_ModeSwitchport_Trunk_EncapsulationVRFVRRP_GroupsZone_Name
2exitgw[GigabitEthernet1]NoneTrueTrue['10.10.100.2/24']True1000000000.0FalseNone[][]['GigabitEthernet1']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.100.2/2410.10.100.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
3exitgw[GigabitEthernet2]NoneTrueTrue['10.10.101.2/24']True1000000000.0FalseNone[][]['GigabitEthernet2']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.101.2/2410.10.101.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
4exitgw[GigabitEthernet3]NoneTrueTrue['147.75.69.27/31']True1000000000.0FalseNone[][]['GigabitEthernet3']NoneNone[]NoneNoneNone1500NoneNoneNone147.75.69.27/31147.75.69.26/31TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
\n", "
" ], "text/plain": [ " Interface Access_VLAN Active Admin_Up All_Prefixes \\\n", "2 exitgw[GigabitEthernet1] None True True ['10.10.100.2/24'] \n", "3 exitgw[GigabitEthernet2] None True True ['10.10.101.2/24'] \n", "4 exitgw[GigabitEthernet3] None True True ['147.75.69.27/31'] \n", "\n", " Allowed_VLANs Auto_State_VLAN Bandwidth Blacklisted Channel_Group \\\n", "2 True 1000000000.0 False None \n", "3 True 1000000000.0 False None \n", "4 True 1000000000.0 False None \n", "\n", " Channel_Group_Members DHCP_Relay_Addresses Declared_Names \\\n", "2 [] [] ['GigabitEthernet1'] \n", "3 [] [] ['GigabitEthernet2'] \n", "4 [] [] ['GigabitEthernet3'] \n", "\n", " Description Encapsulation_VLAN HSRP_Groups HSRP_Version Inactive_Reason \\\n", "2 None None [] None \n", "3 None None [] None \n", "4 None None [] None \n", "\n", " Incoming_Filter_Name MLAG_ID MTU Native_VLAN Outgoing_Filter_Name \\\n", "2 None None 1500 None None \n", "3 None None 1500 None None \n", "4 None None 1500 None None \n", "\n", " PBR_Policy_Name Primary_Address Primary_Network Proxy_ARP Rip_Enabled \\\n", "2 None 10.10.100.2/24 10.10.100.0/24 True False \n", "3 None 10.10.101.2/24 10.10.101.0/24 True False \n", "4 None 147.75.69.27/31 147.75.69.26/31 True False \n", "\n", " Rip_Passive Spanning_Tree_Portfast Speed Switchport Switchport_Mode \\\n", "2 False False 1000000000.0 False NONE \n", "3 False False 1000000000.0 False NONE \n", "4 False False 1000000000.0 False NONE \n", "\n", " Switchport_Trunk_Encapsulation VRF VRRP_Groups Zone_Name \n", "2 DOT1Q default [] None \n", "3 DOT1Q default [] None \n", "4 DOT1Q default [] None " ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Display all active GigabitEthernet interfaces on node 'exitgw'\n", "interfaces[\n", " interfaces.apply(\n", " lambda row: row[\"Interface\"].hostname == \"exitgw\"\n", " and row[\"Interface\"].interface.startswith(\"GigabitEthernet\")\n", " and row[\"Active\"],\n", " axis=1,\n", " )\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Filtering columns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When viewing Batfish answers, you may want to view only some of the columns. Pandas makes that easy for both original answers and answers where some rows have been filtered, as both of them are just DataFrames." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
InterfaceAll_Prefixes
2exitgw[GigabitEthernet1]['10.10.100.2/24']
3exitgw[GigabitEthernet2]['10.10.101.2/24']
4exitgw[GigabitEthernet3]['147.75.69.27/31']
\n", "
" ], "text/plain": [ " Interface All_Prefixes\n", "2 exitgw[GigabitEthernet1] ['10.10.100.2/24']\n", "3 exitgw[GigabitEthernet2] ['10.10.101.2/24']\n", "4 exitgw[GigabitEthernet3] ['147.75.69.27/31']" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Filter interfaces to all active GigabitEthernet interfaces on node exitgw\n", "exitgw_gige_active_interfaces = interfaces[\n", " interfaces.apply(\n", " lambda row: row[\"Interface\"].hostname == \"exitgw\"\n", " and row[\"Interface\"].interface.startswith(\"GigabitEthernet\")\n", " and row[\"Active\"],\n", " axis=1,\n", " )\n", "]\n", "# Display only the Interface and All_Prefixes columns of the filtered DataFrame\n", "exitgw_gige_active_interfaces[[\"Interface\", \"All_Prefixes\"]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Counting rows" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Often, you would be interested in counting the number of rows in the filtered answer. This is super easy because Python's `len()` method, which we use for iterables, can be used on DataFrames as well." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Show the number of rows in the filtered DataFrame that we obtained above\n", "len(exitgw_gige_active_interfaces)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Grouping rows" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For more advanced operations than filtering rows and columns, chances are that you will find Pandas [groupyby](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.groupby.html) pretty handy. This method enables you to group rows using a custom criteria and analyze those groups. For instance, if you wanted to group interfaces by nodes, you may do the following:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "# Get interfaces grouped by node name\n", "intefaces_by_hostname = interfaces.groupby(\n", " lambda index: interfaces.loc[index][\"Interface\"].hostname\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We obtained a Pandas `DataFrameGroupBy` object above. The `groupby` method iterates over row indexes (`apply` iterated over rows), calls the lambda over each, and groups rows whose indices yield the same value. In our example, the lambda first gets the row using `interfaces.loc[index]`, then gets the interface (which is of type `pybatfish.datamodel.primitives.Interface`), and finally the hostname. \n", "\n", "`DataFrameGroupBy` objects offer many functions that are useful for analysis. We demonstrate two of them below." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
InterfaceAccess_VLANActiveAdmin_UpAll_PrefixesAllowed_VLANsAuto_State_VLANBandwidthBlacklistedChannel_GroupChannel_Group_MembersDHCP_Relay_AddressesDeclared_NamesDescriptionEncapsulation_VLANHSRP_GroupsHSRP_VersionInactive_ReasonIncoming_Filter_NameMLAG_IDMTUNative_VLANOutgoing_Filter_NamePBR_Policy_NamePrimary_AddressPrimary_NetworkProxy_ARPRip_EnabledRip_PassiveSpanning_Tree_PortfastSpeedSwitchportSwitchport_ModeSwitchport_Trunk_EncapsulationVRFVRRP_GroupsZone_Name
2exitgw[GigabitEthernet1]NoneTrueTrue['10.10.100.2/24']True1000000000.0FalseNone[][]['GigabitEthernet1']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.100.2/2410.10.100.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
3exitgw[GigabitEthernet2]NoneTrueTrue['10.10.101.2/24']True1000000000.0FalseNone[][]['GigabitEthernet2']NoneNone[]NoneNoneNone1500NoneNoneNone10.10.101.2/2410.10.101.0/24TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
4exitgw[GigabitEthernet3]NoneTrueTrue['147.75.69.27/31']True1000000000.0FalseNone[][]['GigabitEthernet3']NoneNone[]NoneNoneNone1500NoneNoneNone147.75.69.27/31147.75.69.26/31TrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
5exitgw[GigabitEthernet4]NoneFalseFalse[]True1000000000.0FalseNone[][]['GigabitEthernet4']NoneNone[]NoneAdministratively downNoneNone1500NoneNoneNoneNoneNoneTrueFalseFalseFalse1000000000.0FalseNONEDOT1Qdefault[]None
6exitgw[Loopback0]NoneTrueTrue['2.2.2.2/32']True8000000000.0NoneNone[][]['Loopback0']NoneNone[]NoneNoneNone1500NoneNoneNone2.2.2.2/322.2.2.2/32TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
7exitgw[Loopback123]NoneTrueTrue['192.168.123.7/32']True8000000000.0NoneNone[][]['Loopback123']NoneNone[]NoneNoneNone1500NoneNoneNone192.168.123.7/32192.168.123.7/32TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
8exitgw[Tunnel1]NoneTrueTrue['169.254.25.162/30']True100000.0NoneNone[][]['Tunnel1']NoneNone[]NoneNoneNone1500NoneNoneNone169.254.25.162/30169.254.25.160/30TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
9exitgw[Tunnel2]NoneTrueTrue['169.254.172.2/30']True100000.0NoneNone[][]['Tunnel2']NoneNone[]NoneNoneNone1500NoneNoneNone169.254.172.2/30169.254.172.0/30TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
10exitgw[Tunnel3]NoneTrueTrue['169.254.252.78/30']True100000.0NoneNone[][]['Tunnel3']NoneNone[]NoneNoneNone1500NoneNoneNone169.254.252.78/30169.254.252.76/30TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
11exitgw[Tunnel4]NoneTrueTrue['169.254.215.82/30']True100000.0NoneNone[][]['Tunnel4']NoneNone[]NoneNoneNone1500NoneNoneNone169.254.215.82/30169.254.215.80/30TrueFalseFalseFalseNoneFalseNONEDOT1Qdefault[]None
\n", "
" ], "text/plain": [ " Interface Access_VLAN Active Admin_Up \\\n", "2 exitgw[GigabitEthernet1] None True True \n", "3 exitgw[GigabitEthernet2] None True True \n", "4 exitgw[GigabitEthernet3] None True True \n", "5 exitgw[GigabitEthernet4] None False False \n", "6 exitgw[Loopback0] None True True \n", "7 exitgw[Loopback123] None True True \n", "8 exitgw[Tunnel1] None True True \n", "9 exitgw[Tunnel2] None True True \n", "10 exitgw[Tunnel3] None True True \n", "11 exitgw[Tunnel4] None True True \n", "\n", " All_Prefixes Allowed_VLANs Auto_State_VLAN Bandwidth \\\n", "2 ['10.10.100.2/24'] True 1000000000.0 \n", "3 ['10.10.101.2/24'] True 1000000000.0 \n", "4 ['147.75.69.27/31'] True 1000000000.0 \n", "5 [] True 1000000000.0 \n", "6 ['2.2.2.2/32'] True 8000000000.0 \n", "7 ['192.168.123.7/32'] True 8000000000.0 \n", "8 ['169.254.25.162/30'] True 100000.0 \n", "9 ['169.254.172.2/30'] True 100000.0 \n", "10 ['169.254.252.78/30'] True 100000.0 \n", "11 ['169.254.215.82/30'] True 100000.0 \n", "\n", " Blacklisted Channel_Group Channel_Group_Members DHCP_Relay_Addresses \\\n", "2 False None [] [] \n", "3 False None [] [] \n", "4 False None [] [] \n", "5 False None [] [] \n", "6 None None [] [] \n", "7 None None [] [] \n", "8 None None [] [] \n", "9 None None [] [] \n", "10 None None [] [] \n", "11 None None [] [] \n", "\n", " Declared_Names Description Encapsulation_VLAN HSRP_Groups \\\n", "2 ['GigabitEthernet1'] None None [] \n", "3 ['GigabitEthernet2'] None None [] \n", "4 ['GigabitEthernet3'] None None [] \n", "5 ['GigabitEthernet4'] None None [] \n", "6 ['Loopback0'] None None [] \n", "7 ['Loopback123'] None None [] \n", "8 ['Tunnel1'] None None [] \n", "9 ['Tunnel2'] None None [] \n", "10 ['Tunnel3'] None None [] \n", "11 ['Tunnel4'] None None [] \n", "\n", " HSRP_Version Inactive_Reason Incoming_Filter_Name MLAG_ID MTU \\\n", "2 None None None 1500 \n", "3 None None None 1500 \n", "4 None None None 1500 \n", "5 None Administratively down None None 1500 \n", "6 None None None 1500 \n", "7 None None None 1500 \n", "8 None None None 1500 \n", "9 None None None 1500 \n", "10 None None None 1500 \n", "11 None None None 1500 \n", "\n", " Native_VLAN Outgoing_Filter_Name PBR_Policy_Name Primary_Address \\\n", "2 None None None 10.10.100.2/24 \n", "3 None None None 10.10.101.2/24 \n", "4 None None None 147.75.69.27/31 \n", "5 None None None None \n", "6 None None None 2.2.2.2/32 \n", "7 None None None 192.168.123.7/32 \n", "8 None None None 169.254.25.162/30 \n", "9 None None None 169.254.172.2/30 \n", "10 None None None 169.254.252.78/30 \n", "11 None None None 169.254.215.82/30 \n", "\n", " Primary_Network Proxy_ARP Rip_Enabled Rip_Passive \\\n", "2 10.10.100.0/24 True False False \n", "3 10.10.101.0/24 True False False \n", "4 147.75.69.26/31 True False False \n", "5 None True False False \n", "6 2.2.2.2/32 True False False \n", "7 192.168.123.7/32 True False False \n", "8 169.254.25.160/30 True False False \n", "9 169.254.172.0/30 True False False \n", "10 169.254.252.76/30 True False False \n", "11 169.254.215.80/30 True False False \n", "\n", " Spanning_Tree_Portfast Speed Switchport Switchport_Mode \\\n", "2 False 1000000000.0 False NONE \n", "3 False 1000000000.0 False NONE \n", "4 False 1000000000.0 False NONE \n", "5 False 1000000000.0 False NONE \n", "6 False None False NONE \n", "7 False None False NONE \n", "8 False None False NONE \n", "9 False None False NONE \n", "10 False None False NONE \n", "11 False None False NONE \n", "\n", " Switchport_Trunk_Encapsulation VRF VRRP_Groups Zone_Name \n", "2 DOT1Q default [] None \n", "3 DOT1Q default [] None \n", "4 DOT1Q default [] None \n", "5 DOT1Q default [] None \n", "6 DOT1Q default [] None \n", "7 DOT1Q default [] None \n", "8 DOT1Q default [] None \n", "9 DOT1Q default [] None \n", "10 DOT1Q default [] None \n", "11 DOT1Q default [] None " ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Display the rows corresponding to node 'exitgw' group\n", "intefaces_by_hostname.get_group(\"exitgw\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we used the [get_group](https://pandas.pydata.org/docs/reference/api/pandas.core.groupby.GroupBy.get_group.html) method to get all information for 'exitgw', thus viewing all interfaces for that node. This is possible using row filtering as well, but we can do other things that are not, such as:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Interface
__aws-services-gateway__2
exitgw10
i-01602d9efaed4409a1
i-02cae6eaa9edeed701
i-04cd3db5124a05ee61
i-0a5d64b8b58c6dd091
igw-02fd68f94367a67c72
igw-0a8309f3192e7cea32
internet3
isp_165096
isp_652002
leaf115
leaf213
leaf313
leaf414
spine118
spine218
srv-1011
subnet-009d57c7f138136304
subnet-0333a0749ea4ce3df4
subnet-03acae3b9a534fff93
subnet-06005943afe32f7144
subnet-06a692ed4ef84368d4
subnet-09b389def558a9c7d3
subnet-0cb5f4c094bee52143
subnet-0f84a4be105f7aaef3
tgw-06b348adabd13452d8
tgw-0888a76c8a371246d8
vpc-00157b5941bfd49595
vpc-00b65e980771060598
vpc-0276455718806058a5
vpc-0574d08f8d05917e48
\n", "
" ], "text/plain": [ " Interface\n", "__aws-services-gateway__ 2\n", "exitgw 10\n", "i-01602d9efaed4409a 1\n", "i-02cae6eaa9edeed70 1\n", "i-04cd3db5124a05ee6 1\n", "i-0a5d64b8b58c6dd09 1\n", "igw-02fd68f94367a67c7 2\n", "igw-0a8309f3192e7cea3 2\n", "internet 3\n", "isp_16509 6\n", "isp_65200 2\n", "leaf1 15\n", "leaf2 13\n", "leaf3 13\n", "leaf4 14\n", "spine1 18\n", "spine2 18\n", "srv-101 1\n", "subnet-009d57c7f13813630 4\n", "subnet-0333a0749ea4ce3df 4\n", "subnet-03acae3b9a534fff9 3\n", "subnet-06005943afe32f714 4\n", "subnet-06a692ed4ef84368d 4\n", "subnet-09b389def558a9c7d 3\n", "subnet-0cb5f4c094bee5214 3\n", "subnet-0f84a4be105f7aaef 3\n", "tgw-06b348adabd13452d 8\n", "tgw-0888a76c8a371246d 8\n", "vpc-00157b5941bfd4959 5\n", "vpc-00b65e98077106059 8\n", "vpc-0276455718806058a 5\n", "vpc-0574d08f8d05917e4 8" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Display the number of interfaces per node\n", "intefaces_by_hostname.count()[[\"Interface\"]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, we used the [count](https://pandas.pydata.org/docs/reference/api/pandas.core.groupby.DataFrameGroupBy.count.html) method, which counts non-null entries for each column in the group. We then filtered by the `Interface` column to see interfaces per node." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary\n", "\n", "In this notebook, we showed how you can use Pandas methods to manipulate Batfish answers, including filtering rows, filtering columns, and grouping rows. Hopefully, these examples help you get started with your analyses. Find us on Slack (link below) if you have questions." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "### Get involved with the Batfish community\n", "\n", "Join our community on [Slack](https://join.slack.com/t/batfish-org/shared_invite/enQtMzA0Nzg2OTAzNzQ1LTcyYzY3M2Q0NWUyYTRhYjdlM2IzYzRhZGU1NWFlNGU2MzlhNDY3OTJmMDIyMjQzYmRlNjhkMTRjNWIwNTUwNTQ) and [GitHub](https://github.com/batfish/batfish). " ] } ], "metadata": { "hide_input": false, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.15" } }, "nbformat": 4, "nbformat_minor": 2 }