首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Pandas -以正确的方式连接两个不同结构的JSON

Pandas -以正确的方式连接两个不同结构的JSON
EN

Stack Overflow用户
提问于 2018-06-03 20:51:07
回答 2查看 1.3K关注 0票数 2

我知道有很多类似的问题,但我仍然觉得我在这里做错了很多事情,我相信你们中的一些人可以帮助我,给我一些未来的建议,我尝试了许多不同的方法,但仍然不能正常工作。

我有以下两个数据源,我想和熊猫一起加入。

第一个带有属性的-让我们称之为 json json

代码语言:javascript
复制
[
{
    "propertyDetails": {
        "accountId": 102864,
        "availableFromFormatted": "On request",
        "cityName": "Derendingen",
        "contactFormTypeId": 3,
        "countryId": 1,
        "description": "Mehr erfahren: F\u00fcr weitere Bilder, Informationen zu Raumangebot, Gemeinde und Lage besuchen sie uns auf www.immostema.ch und geben Sie oben rechts im Suchfeld die Objektnummer I0398 ein. Wir freuen uns auf Sie!  \r\n  \r\n\r\n\r\n**Schauen Sie sich das Kurzvideo an:**  \r\n[https://youtu.be/xyD9oX4nmDQ](https://youtu.be/xyD9oX4nmDQ)  \r\n  \r\nIn Derendingen im Kanton Solothurn, verkaufen wir an ruhiger Wohnlage dieses **5\u00bd-Zimmer-Einfamilienhaus**(Doppeleinfamilienhaush\u00e4lfte). Das Haus, im Jahr 2013 erbaut, wurde mit qualitativ hochwertigen Materialen Innen ausgebaut. Das Haus eignet sich sehr gut f\u00fcr Familien und bietet sehr sch\u00f6nes und ruhiges Wohnen.   \r\nZum Haus geh\u00f6ren auch ein Autounterstand mit Ger\u00e4teraum sowie ein zus\u00e4tzlicher Parkplatz.   \r\n  \r\n**Hier die Eckdaten:**\r\n\r\n\r\n- Einfamilienhaus mit 5\u00bd - Zimmer\r\n- Grundst\u00fcck: 221 m\u00b2\r\n- Wohnfl\u00e4che: 141 m\u00b2\r\n- Nutzfl\u00e4che: 216 m\u00b2\r\n- Hochwertiger Innenausbau\r\n- W\u00e4rmepumpe\r\n- Fussbodenheizung\r\n- Grosse gedeckte Terrasse\r\n- Grosser Balkon\r\n- 1 Autounterstand mit grossem Ger\u00e4teraum zur Eigennutzung\r\n- 1 Parkplatz\r\n\r\n\r\n\r\nSchulen, Einkaufsm\u00f6glichkeiten, Banken, Post, erreicht man in wenigen Minuten.   \r\nBusbetrieb Solothurn und Umgebung (BSU) verkehrt im 15 Minutentakt. Die Bushaltestelle befindet sich nur 50m vom Haus entfernt.  \r\n  \r\nVerlangen Sie die detaillierte Verkaufsdokumentation.\r\n\r\n",
        "geoAccuracy": 8,
        "id": 4998203
    },
    "propertyDetailsView": {
        "accountPropertiesUrl": "/en/agency-properties/immostema-ag/102864"
    }
},
{
    "propertyDetails": {
        "accountId": 98465,
        "attributesSize": {
            "numberOfFloors": 4
        },
        "attributesSurrounding": {
            "distanceShop": 100,
            "distanceShopFormatted": "Approx. 100 m",
            "distanceKindergarten": 100,
            "distanceKindergartenFormatted": "Approx. 100 m",
            "distanceSchool1": 100,
            "distanceSchool1Formatted": "Approx. 100 m",
            "distanceSchool2": 200,
            "distanceSchool2Formatted": "Approx. 200 m",
            "distancePublicTransport": 200,
            "distancePublicTransportFormatted": "Approx. 200 m",
            "distanceMotorway": 6000,
            "distanceMotorwayFormatted": "Approx. 6000 m"
        },
        "attributes": {
            "yearBuilt": 1846
        },
        "availableFrom": "2018-05-30T00:00:00",
        "availableFromFormatted": "Immediately",
        "cityName": "Koppigen",
        "contactFormTypeId": 3,
        "countryId": 1,
        "description": " \r\n\r\n**Was es scho het**\r\n\r\n \r\n\r\nEin altehrw\u00fcrdiges Bauernhaus nahe dem Dorfzentrum.\r\n\r\n \r\n\r\n**Was es darf g\u00e4**\r\n\r\n \r\n\r\nGeplant ist ein umfassender Umbau des Bauernhauses mit der Erstellung von vier 3.5-Zimmer- und zwei 4.5-Zimmer-Wohnungen.\r\n\r\n \r\n\r\n**Me cha grad loslege, muess aber nid**\r\n\r\n \r\n\r\nDie Baubewilligung wurde bereits erteilt und ist g\u00fcltig bis Ende Dezember 2018. Der Kauf der Parzelle, inkl. aller bestehenden Bauten, ist auch ohne Realisierung des Projekts m\u00f6glich.\r\n\r\n \r\n\r\n**Meh gits hie**\r\n\r\n \r\n\r\nUnsere Verkaufsdokumentation mit detailliertem Baubeschrieb, umfassenden Planunterlagen\u00a0und vielem mehr liegt f\u00fcr Sie bereit. Gerne empfangen wir Sie auch bei uns im B\u00fcro, um Ihnen die gesamte \u00dcberbauung detailliert zu erkl\u00e4ren.\r\n\r\n \r\n\r\nIn diesem Sinne: Wir freuen uns, von Ihnen zu h\u00f6ren - bis gli!\r\n\r\n ",
        "geoAccuracy": 8,
        "id": 4998826            
    },
    "propertyDetailsView": {
        "accountPropertiesUrl": "/en/agency-properties/immosky-ag---aargau/238044"          
    }
}
]

我自己创建的第二个字典文件-让我们称之为json2:*备注A:如果生成JSON文件,是否将id作为关键字放入字典中,或者是否将关键字作为"id“添加为列?我认为它作为一个列更好,因为当它是一个列时,在pandas中使用set_index()更容易,但是不确定?

代码语言:javascript
复制
  {
  "4998203": {
  "id": 4998203,
  "routeDepartureCity": "47.20959, 7.5326",
  "routeDestinationCity": "solothurn Hauptbahnhof",
  "routeDurationSecCity": 455,
  "routeDistanceMetersCity": 1044,
  "transitsAllCity": 2,
  "transitsNoWalkingCity": 1,
  "routeDepartureWork": "47.20959, 7.5326",
  "routeDestinationWork": "swissqual, Allmendweg 8, 4528 Zuchwil",
  "routeDurationSecWork": 1129,
  "routeDistanceMetersWork": 3060,
  "transitsAllWork": 3,
  "transitsNoWalkingWork": 1
}

}

在我可以将它们加载到pandas数据帧之前,我用我在网上找到的以下函数对json1进行了扁平化:

代码语言:javascript
复制
def flatten_json(y):
out = {}

def flatten(x, name=''):
    if type(x) is dict:
        for a in x:
            if a not in ('images'):
                flatten(x[a], name + a + '_')
    elif type(x) is list:
        i = 0
        for a in x:
            flatten(a, name + str(i) + '_')
            i += 1
    else:
        out[name[:-1]] = x

flatten(y)
return out

它看起来像这样:

代码语言:javascript
复制
import ijson, json
import pandas as pd

with open(json1, 'r') as f:
    #using ijson as this file might be big
    objects = ijson.items(f, 'item.propertyDetails')
    props = list(objects)

p = []
for prop in props:
    #flatten all dics/arrays inside
    p.append(flatten_json(prop))

#load into pandas including setting index:
dfprop = pd.DataFrame(p).set_index('id')

这工作得很好,而且索引似乎设置正确。现在我加载第二个json2文件:

代码语言:javascript
复制
d = json.load(open(json2, 'rb'))
dfWayCalc = pd.DataFrame.from_dict(d)

dfWayCalc = dfWayCalc.transpose()  # switch cols and rows
dfWayCalc.set_index('id')

如果我想将它加入到pandas中,它不会给我一个错误,但是我无法从id=4998203的json2中找到正确的值。它始终是NaN,而不是实际值。这是我尝试的方式(许多版本中的一个):

代码语言:javascript
复制
m = dfprop.join(dfWayCalc, how='left')

m.loc[4998203] #doesn't show the values from json2

#if i print json2, i see the values:
print(dfWayCalc.loc['4998203'])

我做错了什么?基于索引进行此连接的正确方法是什么?我很感谢你的帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-04 11:22:29

考虑一下pandas的json_normalize,它可以从嵌套的json数据构建数据帧,然后像任何数据帧一样合并这两个集:

代码语言:javascript
复制
import json as json
import pandas as pd
from pandas.io.json import json_normalize

# FIRST JSON
with open('json1.json', 'r') as f:
    data = json.loads(f.read())    

df_list = [json_normalize(i['propertyDetails']) for i in data]
details_df = pd.concat(df_list, ignore_index=True)

# SECOND JSON
with open('json2.json', 'r') as f:
    data = json.loads(f.read())

df_list = [pd.DataFrame(data[i], index=[0]) for i in data]
id_df = pd.concat(df_list, ignore_index=True)

# MERGE BOTH DATAFRAMES    
final_df = pd.merge(details_df, id_df, on='id', how='left')

CodePen Output ( final_df数据帧的html版本)

票数 2
EN

Stack Overflow用户

发布于 2018-06-04 06:21:28

我找到了解决方案。

这很简单,所有的列都是对象,因此不能连接。另外,设置索引没有保存,因为没有重新分配给数据帧。这就是将两个数据帧结合在一起的方法:

代码语言:javascript
复制
d = json.load(open(json2, 'rb'))
dfWayCalc = pd.DataFrame.from_dict(d)

dfWayCalc = dfWayCalc.transpose()  # switch cols and rows
dfWayCalc.set_index('id')

#converting to integer was missing, all columns were type object:
dfWayCalc = dfWayCalc.apply(pd.to_numeric, errors='ignore')

#the dfWayCalc asignment was missing, so the index wasn't saved
dfWayCalc = df.set_index('id')
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50666614

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档