Python 3.x 使用python条件连接RDD

Python 3.x 使用python条件连接RDD,python-3.x,pyspark,Python 3.x,Pyspark,我有两个RDD。第一个包含与IP地址相关的信息(参见第c列IP): 另一个RDD是IP地理定位 network,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider,postal_code,latitude,longitude,accuracy_radius 1.0.0.0/24,2077456,2077456,,0,0,,-

我有两个RDD。第一个包含与IP地址相关的信息(参见第c列IP):

另一个RDD是IP地理定位

network,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider,postal_code,latitude,longitude,accuracy_radius
1.0.0.0/24,2077456,2077456,,0,0,,-33.4940,143.2104,1000
1.0.1.0/24,1810821,1814991,,0,0,,26.0614,119.3061,50
1.0.2.0/23,1810821,1814991,,0,0,,26.0614,119.3061,50
1.0.4.0/22,2077456,2077456,,0,0,,-33.4940,143.2104,1000
我想匹配这两个,但问题是在两个RDD中的列之间没有严格的等价物

我想使用Python3软件包ipaddress并执行如下检查:

> import ipaddress
> ipaddress.IPv4Address('1.0.0.5') in ipaddress.ip_network('1.0.0.0/24')
True

是否可以使用python函数来执行连接(左外部连接以不从我的第一个RDD中排除任何行)?我该怎么做

使用ApacheSpark 1.6时,您仍然可以在连接中使用UDF函数作为谓词。生成一些测试数据后:

import ipaddress
from pyspark.sql.functions import udf
from pyspark.sql.types import StringType, StructField, StructType, BooleanType, ArrayType, IntegerType

sessions = sc.parallelize([(1608422,'119.228.181.78'),(1608423, '119.228.181.78')]).toDF(['unic_key','c_ip'])

geo_ip = sc.parallelize([('1.0.0.0/24',2077456,2077456),
                        ('1.0.1.0/24',1810821,1814991),
                        ('1.0.2.0/23',1810821,1814991),
                        ('1.0.4.0/22',2077456,2077456)]).toDF(['network','geoname_id','registered_country_geoname_id'])
您可以按如下方式创建UDF谓词:

def ip_range(ip, network_range):
    return ipaddress.IPv4Address(unicode(ip)) in ipaddress.ip_network(unicode(network_range))

pred = udf(lambda ip, network_range:ipaddress.IPv4Address(unicode(ip)) in ipaddress.ip_network(unicode(network_range)), BooleanType())
然后,如果满足以下条件,则可以使用UDF:

sessions.join(geo_ip).where(pred(sessions.c_ip, geo_ip.network))

不幸的是,这在Spark 2.x中目前不起作用,请参见您使用的Spark的哪个版本?1.x或2.x?我使用spark 1.6
sessions.join(geo_ip).where(pred(sessions.c_ip, geo_ip.network))