将 json 文件转换为 python 和 FourSqaure API 中的数据帧

Convert json file to dataframe in python and FourSqaure API

我正在 Coursera 上完成这项 IBM 数据科学认证,其中一项作业要求我们复制此 link- https://rawnote.dinhanhthi.com/files/ibm/neighborhoods_in_toronto.

我对此很陌生,所以我通过 link 来理解它,但我无法理解代码的某些部分。

所以这个作业的objective是:

  1. 从维基百科中提取 table 并将其存储在数据框中
  2. 创建多伦多市地图并探索包含 "Toronto"
  3. 的行政区
  4. 使用 FourSqaure API 探索多伦多的任何随机社区(此处已选择 "The Beaches")
  5. 获取"The Beaches"半径500米范围内的前100个场馆。

他们使用 FourSqaure API 完成了第四点,如下所示:

LIMIT = 100 # limit of number of venues returned by Foursquare API
radius = 500 # define radius
url = 'https://api.foursquare.com/v2/venues/explore?&client_id={}&client_secret={}&v={}&ll={},{}&radius={}&limit={}'.format(
    CLIENT_ID, 
    CLIENT_SECRET, 
    VERSION, 
    neighborhood_latitude, 
    neighborhood_longitude, 
    radius, 
    LIMIT)

# get the result to a json file
results = requests.get(url).json()

"results" 变量如下所示:

{'meta': {'code': 200, 'requestId': '5eda4fb9aba297001b2f6207'},
 'response': {'headerLocation': 'The Beaches',
  'headerFullLocation': 'The Beaches, Toronto',
  'headerLocationGranularity': 'neighborhood',
  'totalResults': 4,
  'suggestedBounds': {'ne': {'lat': 43.680857404499996,
    'lng': -79.28682091449052},
   'sw': {'lat': 43.67185739549999, 'lng': -79.29924148550948}},
  'groups': [{'type': 'Recommended Places',
    'name': 'recommended',
    'items': [{'reasons': {'count': 0,
       'items': [{'summary': 'This spot is popular',
         'type': 'general',
         'reasonName': 'globalInteractionReason'}]},
      'venue': {'id': '4bd461bc77b29c74a07d9282',
       'name': 'Glen Manor Ravine',
       'location': {'address': 'Glen Manor',
        'crossStreet': 'Queen St.',
        'lat': 43.67682094413784,
        'lng': -79.29394208780985,
        'labeledLatLngs': [{'label': 'display',
          'lat': 43.67682094413784,
          'lng': -79.29394208780985}],
        'distance': 89,
        'cc': 'CA',
        'city': 'Toronto',
        'state': 'ON',
        'country': 'Canada',
        'formattedAddress': ['Glen Manor (Queen St.)',
         'Toronto ON',
         'Canada']},
       'categories': [{'id': '4bf58dd8d48988d159941735',
         'name': 'Trail',
         'pluralName': 'Trails',
         'shortName': 'Trail',
         'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/parks_outdoors/hikingtrail_',
          'suffix': '.png'},
         'primary': True}],
       'photos': {'count': 0, 'groups': []}},
      'referralId': 'e-0-4bd461bc77b29c74a07d9282-0'},
     {'reasons': {'count': 0,
       'items': [{'summary': 'This spot is popular',
         'type': 'general',
         'reasonName': 'globalInteractionReason'}]},
      'venue': {'id': '4ad4c062f964a52011f820e3',
       'name': 'The Big Carrot Natural Food Market',
       'location': {'address': '125 Southwood Dr',
        'lat': 43.678879,
        'lng': -79.297734,
        'labeledLatLngs': [{'label': 'display',
          'lat': 43.678879,
          'lng': -79.297734}],
        'distance': 471,
        'postalCode': 'M4E 0B8',
        'cc': 'CA',
        'city': 'Toronto',
        'state': 'ON',
        'country': 'Canada',
        'formattedAddress': ['125 Southwood Dr',
         'Toronto ON M4E 0B8',
         'Canada']},
       'categories': [{'id': '50aa9e744b90af0d42d5de0e',
         'name': 'Health Food Store',
         'pluralName': 'Health Food Stores',
         'shortName': 'Health Food Store',
         'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/shops/food_grocery_',
          'suffix': '.png'},
         'primary': True}],
       'photos': {'count': 0, 'groups': []},
       'venuePage': {'id': '75150878'}},
      'referralId': 'e-0-4ad4c062f964a52011f820e3-1'},
     {'reasons': {'count': 0,
       'items': [{'summary': 'This spot is popular',
         'type': 'general',
         'reasonName': 'globalInteractionReason'}]},
      'venue': {'id': '4b8daea1f964a520480833e3',
       'name': 'Grover Pub and Grub',
       'location': {'address': '676 Kingston Rd.',
        'crossStreet': 'at Main St.',
        'lat': 43.679181434941015,
        'lng': -79.29721535878515,
        'labeledLatLngs': [{'label': 'display',
          'lat': 43.679181434941015,
          'lng': -79.29721535878515}],
        'distance': 460,
        'postalCode': 'M4E 1R4',
        'cc': 'CA',
        'city': 'Toronto',
        'state': 'ON',
        'country': 'Canada',
        'formattedAddress': ['676 Kingston Rd. (at Main St.)',
         'Toronto ON M4E 1R4',
         'Canada']},
       'categories': [{'id': '4bf58dd8d48988d11b941735',
         'name': 'Pub',
         'pluralName': 'Pubs',
         'shortName': 'Pub',
         'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/nightlife/pub_',
          'suffix': '.png'},
         'primary': True}],
       'photos': {'count': 0, 'groups': []}},
      'referralId': 'e-0-4b8daea1f964a520480833e3-2'},
     {'reasons': {'count': 0,
       'items': [{'summary': 'This spot is popular',
         'type': 'general',
         'reasonName': 'globalInteractionReason'}]},
      'venue': {'id': '4df91c4bae60f95f82229ad5',
       'name': 'Upper Beaches',
       'location': {'lat': 43.68056321147582,
        'lng': -79.2928688743688,
        'labeledLatLngs': [{'label': 'display',
          'lat': 43.68056321147582,
          'lng': -79.2928688743688}],
        'distance': 468,
        'cc': 'CA',
        'city': 'Toronto',
        'state': 'ON',
        'country': 'Canada',
        'formattedAddress': ['Toronto ON', 'Canada']},
       'categories': [{'id': '4f2a25ac4b909258e854f55f',
         'name': 'Neighborhood',
         'pluralName': 'Neighborhoods',
         'shortName': 'Neighborhood',
         'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/parks_outdoors/neighborhood_',
          'suffix': '.png'},
         'primary': True}],
       'photos': {'count': 0, 'groups': []}},
      'referralId': 'e-0-4df91c4bae60f95f82229ad5-3'}]}]}}

我不确定如何进行。下图是link中提到的但是:

  1. 我不明白他们为什么要创建一个函数 get_category_row?
  2. 我们为什么写 venues = results['response']['groups'][0]['items']?不是 json_normalize() 应该将 json 文件转换为 datframe?那我们为什么不能 直接做 json_normalize(results)?

从 link 的第 4.6 节开始,我几乎迷路了。

如果有人能帮助我或指导我,那就太好了! :)

不,你完全错了json_normalize() 将半结构化 JSON 数据标准化为平面数据 table 而不是 DataFrame。这就是为什么他们使用 venues = results['response']['groups'][0]['items'] 来获取场地。他们使用函数 get_category_type() 来获取场地的类别。

如果您想了解更多关于json_normalize()的信息,请参考this link

json_normalize只会展平一个路径中的记录,例如在你的json中,你可以分别展平每个路径:

meta
response -> suggestedBounds
response -> groups -> items

然后你必须将它们合并在一起

df1 = pd.json_normalize(d['response'], record_path=['groups', 'items'], meta=[])
print(df1)
df2 = pd.json_normalize(d['response'])
print(df2)
df3 = pd.json_normalize(d['meta'])
print(df3)


                       referralId  reasons.count  ... venue.location.postalCode venue.venuePage.id
0  e-0-4bd461bc77b29c74a07d9282-0              0  ...                       NaN                NaN
1  e-0-4ad4c062f964a52011f820e3-1              0  ...                   M4E 0B8           75150878
2  e-0-4b8daea1f964a520480833e3-2              0  ...                   M4E 1R4                NaN
3  e-0-4df91c4bae60f95f82229ad5-3              0  ...                       NaN                NaN

[4 rows x 21 columns]
  headerLocation    headerFullLocation headerLocationGranularity  ...  suggestedBounds.ne.lng suggestedBounds.sw.lat  suggestedBounds.sw.lng
0    The Beaches  The Beaches, Toronto              neighborhood  ...              -79.286821              43.671857              -79.299241

[1 rows x 9 columns]
   code                 requestId
0   200  5eda4fb9aba297001b2f6207

如果想把满json压平,可以试试flatten_json。文档:Flatten JSON