Как реализовать этот случай с помощью функции apply в пандах?

1

У меня есть следующий код для получения 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: ("Объект" Серии "не имеет атрибута" rstrip "," произошел с индексом 0 ")

Как я могу это исправить?

  • 0
    rstrip() - это функция, которая работает только со строками. Кажется, вы используете его с ip.rstrip() объектом, но я не уверен, где ( ip.rstrip() - единственное вхождение rstrip() , а ip , скорее всего, строка)
Теги:
pandas
loops
apply

1 ответ

1
Лучший ответ

rstrip - операция строки. Чтобы применить операцию строки к серии Series вы должны сначала вызвать функцию str в серии, которая позволяет выполнять операции векторизованных строк в Series.

В частности, в вашем коде изменения ip.rstrip() на ip.str.rstrip() должны разрешить ваш AttributeError.

После того, как копаться немного выясняется requests.get операции, которую вы пытаетесь выполнить не может быть векторизации в pandas (см Использование Python запросов для нескольких URLS в dataframe). Я взломал следующее, которое должно быть немного более эффективным, чем использование iterrows. Что делает следующее: np.vectorize используется для запуска функции для получения информации для каждого IP-адреса. Вход в местоположение сохраняется как новые столбцы в новом DataFrame.

Во-первых, я изменил вашу функцию get_ip чтобы вернуть словарь location, а не (location).

Затем я создал функцию векторизации, используя np.vectorize:

vec_func = np.vectorize(lambda url: get_ip(url))

Наконец, vec_func применяется к df для создания нового DataFrame, который объединяет df с выводом местоположения из vec_func где df[0] - столбец с вашими URL-адресами:

new_df = pd.concat([df, pd.DataFrame(vec_func(df[0]), columns=["response"])["response"].apply(pd.Series)], axis=1)

Приведенный выше код возвращает ответ API в виде словаря для каждой строки в вашем DataFrame, а затем сопоставляет словарь с столбцами в 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().

  • 0
    Изменяя его, я получаю еще одну ошибку: InvalidSchema: («Не найдено адаптеров соединения для« ip_address ipapi ..., dtype: object »», «произошло с индексом 0») Я следовал решениям по этой [ссылке] ( stackoverflow. ru / questions / 15115328 /… ) и я все еще получаю сообщение об ошибке.
  • 0
    Можете ли вы предоставить полный URL, который вызывает эту новую ошибку?
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню