Панды, использующие netaddr на 2 фреймах данных, чтобы увидеть, попадает ли столбец ip в столбец cidr с логическим результатом - PullRequest
0 голосов
/ 01 марта 2019

Я работаю с библиотекой python netaddr.У меня есть 2 кадра данных, один с диапазонами IP-адресов, которые я преобразую в нотацию CIDR, а другой - с IP-адресом, который я хотел бы видеть, попадают ли они в какой-либо из диапазонов.

Создать диапазон данных:

import pandas as pd
import netaddr
from netaddr import *

a = {'StartAddress': ['65.14.88.64', '148.77.37.88', '65.14.41.128', '65.14.40.0'],
 'EndAddress': ['65.14.88.95', '148.77.37.95','65.14.41.135', '65.14.40.255']}
df1 = pd.DataFrame(data=a)

#Convert range to netaddr cidr format
def rangetocidr(row):
    return netaddr.iprange_to_cidrs(row.StartAddress, row.EndAddress)    

df1["CIDR"] = df1.apply(rangetocidr, axis=1)

df1
    StartAddress  EndAddress    CIDR
0   65.14.88.64   65.14.88.95   [65.14.88.64/27]
1   148.77.37.88  148.77.37.95  [148.77.37.88/29]
2   65.14.41.128  65.14.41.135  [65.14.41.128/29]
3   65.14.40.0    65.14.40.255  [65.14.40.0/24]

df1["CIDR"].iloc[0]
[IPNetwork('65.14.88.64/27')]

Создание IP-фрейма данных:

b = {'IP': ['65.13.88.64', '148.65.37.88','65.14.88.65','148.77.37.93','66.15.41.132']}
df2 = pd.DataFrame(data=b)

#Convert ip to netaddr format
def iptonetaddrformat (row):
    return netaddr.IPAddress(row.IP)

df2["IP_Format"] = df2.apply(iptonetaddrformat, axis=1)
df2
    IP            IP_Format
0   65.13.88.64   65.13.88.64
1   148.65.37.88  148.65.37.88
2   65.14.88.65   65.14.88.65
3   148.77.37.93  148.77.37.93
4   66.15.41.132  66.15.41.132

df2["IP_Format"].iloc[0]
IPAddress('65.13.88.64')

Я хочу добавить столбец к df2, если ips находятся в блоках cidr с df1.Таким образом, это выглядело бы так:

df2
    IP            IP_Format     IN_CIDR
0   65.13.88.64   65.13.88.64   False
1   148.65.37.88  148.65.37.88  False
2   65.14.88.65   65.14.88.65   True
3   148.77.37.93  148.77.37.93  True
4   66.15.41.132  66.15.41.132  False

Я бы предпочел выполнить это, просто используя столбцы из двух фреймов данных, но попытался сделать это путем преобразования столбцов в списки и использования следующего, но, похоже, это не работает:1014 *

df2list = repr(df2[['IP_Format']])
df1list = df[['CIDR']]

def ipincidr (row):
    return netaddr.largest_matching_cidr(df2list, df1list)

df2['INRANGE'] = df2.apply(ipincidr, axis=1)

1 Ответ

0 голосов
/ 01 марта 2019

Следующее решение основано на предположении, что только четвертая группа IP-адресов изменяется, а первые три остаются неизменными, как показано в вопросе.


# Splitting IP into 2 parts __.__.__ and __. 
# Doing this for IP from df2 along with Start and End columns from df1

ip = pd.DataFrame(df2.IP.str.rsplit('.', 1, expand=True))
ip.columns = ['IP_init', 'IP_last']

start = pd.DataFrame(df1.StartAddress.str.rsplit('.', 1, expand=True))
start.columns = ['start_init', 'start_last']

end = pd.DataFrame(df1.EndAddress.str.rsplit('.', 1, expand=True))
end.columns = ['end_init', 'end_last']

df = pd.concat([ip, start, end], axis=1)

# Checking if any IP belongs to any of the given blocks, if yes, note their index

index = []
for idx, val in enumerate(df.itertuples()):
    for i in range(df.start_init.count()):
        if df.loc[idx, 'IP_init'] == df.loc[i, 'start_init']:            
            if df.loc[idx, 'IP_last'] >= df.loc[i, 'start_last'] 
                  and df.loc[idx, 'IP_last'] <= df.loc[i, 'end_last']:
                index.append(idx)
                break


# Creating column IN_CIDR and marking True against the row which exists in IP block

df2['IN_CIDR'] = False
df2.loc[index, 'IN_CIDR'] = True
df2

    IP            IP_Format     IN_CIDR
0   65.13.88.64   65.13.88.64   False
1   148.65.37.88  148.65.37.88  False
2   65.14.88.65   65.14.88.65   True
3   148.77.37.93  148.77.37.93  True
4   66.15.41.132  66.15.41.132  False

Примечание. Вы также можете использовать np.where дляпропустите первую итерацию, используя np.where(df.IP_init.isin(df.start_init), True, False), что приводит к [False, False, True, True, False], и, следовательно, вы можете сосредоточиться позже только на True строках и, таким образом, сократить накладные расходы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...