如何使用 pandas 中的 apply 函数实现这个 iterrow 案例?
How to implement this iterrow case using an apply function in pandas?
我有以下获取IP信息的代码:
import requests
import json
import pandas as pd
import swifter
def get_ip(ip):
response = requests.get ("http://ip-api.com/json/" + ip.rstrip())
geo = response.json()
location = {'lat': geo.get('lat', ''),
'lon': geo.get('lon', ''),
'region': geo.get('regionName', ''),
'city': geo.get('city', ''),
'org': geo.get('org', ''),
'country': geo.get('countryCode', ''),
'query': geo.get('query', '')
}
return(location)
为了将它应用到整个 IP 数据帧 (df),我正在使用下一个:
df=pd.DataFrame(['85.56.19.4','188.85.165.103','81.61.223.131'])
for lab,row in df.iterrows():
dip = get_ip(df.iloc[lab][0])
try:
ip.append(dip["query"])
private.append('no')
country.append(dip["country"])
city.append(dip["city"])
region.append(dip["region"])
organization.append(dip["org"])
latitude.append(dip["lat"])
longitude.append(dip["lon"])
except:
ip.append(df.iloc[lab][0])
private.append("yes")
但是,由于iterrows非常慢,而且我需要更高的性能,所以我想使用swiftapply,它是apply函数的扩展。我用过这个:
def ip(x):
dip = get_ip(x)
if (dip['ip']=='private')==True:
ip.append(x)
private.append("yes")
else:
ip.append(dip["ip"])
private.append('no')
country.append(dip["country"])
city.append(dip["city"])
region.append(dip["region"])
organization.append(dip["org"])
latitude.append(dip["lat"])
longitude.append(dip["lon"])
df.swifter.apply(ip)
我收到以下错误:
AttributeError: ("'Series' 对象没有属性 'rstrip'", 'occurred at index 0')
我该如何解决?
rstrip
是字符串操作。为了对系列 Series
应用字符串操作,您必须首先对该系列调用 str
函数,它允许对 Series
.[=36 执行矢量化字符串操作=]
具体来说,在您的代码中将 ip.rstrip()
更改为 ip.str.rstrip()
应该可以解决您的 AttributeError
.
稍微深入研究后发现,您尝试执行的 requests.get
操作无法在 pandas
内矢量化(请参阅 )。我破解了以下内容,应该比使用 iterrows
更有效。下面做的是利用np.vectorize
到运行函数获取每个IP地址的信息。位置输入被保存为新 DataFrame 中的新列。
首先,我将您的 get_ip
函数更改为 return location
字典,而不是 (location)
。
接下来,我使用 np.vectorize
创建了一个向量化函数:
vec_func = np.vectorize(lambda url: get_ip(url))
最后,vec_func
应用于 df
以创建一个新的 DataFrame,它将 df
与 vec_func
的位置输出合并,其中 df[0]
是包含您的网址的列:
new_df = pd.concat([df, pd.DataFrame(vec_func(df[0]), columns=["response"])["response"].apply(pd.Series)], axis=1)
上面的代码以字典形式检索 DataFrame 中每一行的 API 响应,然后将字典映射到 DataFrame 中的列。最后,您的新 DataFrame 将如下所示:
0 lat lon region city org country query
0 85.56.19.4 37.3824 -5.9761 Andalusia Seville Orange Espana ES 85.56.19.4
1 188.85.165.103 41.6561 -0.8773 Aragon Zaragoza Vodafone Spain ES 188.85.165.103
2 81.61.223.131 40.3272 -3.7635 Madrid Leganés Vodafone Ono ES 81.61.223.131
希望这可以解决 InvalidSchema
错误并让您获得比 iterrows()
更好的性能。
我有以下获取IP信息的代码:
import requests
import json
import pandas as pd
import swifter
def get_ip(ip):
response = requests.get ("http://ip-api.com/json/" + ip.rstrip())
geo = response.json()
location = {'lat': geo.get('lat', ''),
'lon': geo.get('lon', ''),
'region': geo.get('regionName', ''),
'city': geo.get('city', ''),
'org': geo.get('org', ''),
'country': geo.get('countryCode', ''),
'query': geo.get('query', '')
}
return(location)
为了将它应用到整个 IP 数据帧 (df),我正在使用下一个:
df=pd.DataFrame(['85.56.19.4','188.85.165.103','81.61.223.131'])
for lab,row in df.iterrows():
dip = get_ip(df.iloc[lab][0])
try:
ip.append(dip["query"])
private.append('no')
country.append(dip["country"])
city.append(dip["city"])
region.append(dip["region"])
organization.append(dip["org"])
latitude.append(dip["lat"])
longitude.append(dip["lon"])
except:
ip.append(df.iloc[lab][0])
private.append("yes")
但是,由于iterrows非常慢,而且我需要更高的性能,所以我想使用swiftapply,它是apply函数的扩展。我用过这个:
def ip(x):
dip = get_ip(x)
if (dip['ip']=='private')==True:
ip.append(x)
private.append("yes")
else:
ip.append(dip["ip"])
private.append('no')
country.append(dip["country"])
city.append(dip["city"])
region.append(dip["region"])
organization.append(dip["org"])
latitude.append(dip["lat"])
longitude.append(dip["lon"])
df.swifter.apply(ip)
我收到以下错误: AttributeError: ("'Series' 对象没有属性 'rstrip'", 'occurred at index 0')
我该如何解决?
rstrip
是字符串操作。为了对系列 Series
应用字符串操作,您必须首先对该系列调用 str
函数,它允许对 Series
.[=36 执行矢量化字符串操作=]
具体来说,在您的代码中将 ip.rstrip()
更改为 ip.str.rstrip()
应该可以解决您的 AttributeError
.
稍微深入研究后发现,您尝试执行的 requests.get
操作无法在 pandas
内矢量化(请参阅 iterrows
更有效。下面做的是利用np.vectorize
到运行函数获取每个IP地址的信息。位置输入被保存为新 DataFrame 中的新列。
首先,我将您的 get_ip
函数更改为 return location
字典,而不是 (location)
。
接下来,我使用 np.vectorize
创建了一个向量化函数:
vec_func = np.vectorize(lambda url: get_ip(url))
最后,vec_func
应用于 df
以创建一个新的 DataFrame,它将 df
与 vec_func
的位置输出合并,其中 df[0]
是包含您的网址的列:
new_df = pd.concat([df, pd.DataFrame(vec_func(df[0]), columns=["response"])["response"].apply(pd.Series)], axis=1)
上面的代码以字典形式检索 DataFrame 中每一行的 API 响应,然后将字典映射到 DataFrame 中的列。最后,您的新 DataFrame 将如下所示:
0 lat lon region city org country query
0 85.56.19.4 37.3824 -5.9761 Andalusia Seville Orange Espana ES 85.56.19.4
1 188.85.165.103 41.6561 -0.8773 Aragon Zaragoza Vodafone Spain ES 188.85.165.103
2 81.61.223.131 40.3272 -3.7635 Madrid Leganés Vodafone Ono ES 81.61.223.131
希望这可以解决 InvalidSchema
错误并让您获得比 iterrows()
更好的性能。