Heim  >  Artikel  >  Backend-Entwicklung  >  Python führt verschachteltes JSON ein, um es in Sekundenschnelle in Dataframe umzuwandeln!

Python führt verschachteltes JSON ein, um es in Sekundenschnelle in Dataframe umzuwandeln!

coldplay.xixi
coldplay.xixiOriginal
2020-12-29 09:34:393357Durchsuche

Python Tutorial Die Spalte führt vor JSON-Objekt: Wenn wir mit Python versuchen, die Schlüssel in der verschachtelten Struktur in Spalten umzuwandeln, erhalten die in pandas geladenen Daten häufig das Folgendes Ergebnis:

df = pd.DataFrame.from_records(results [“ issues”],columns = [“ key”,“ fields”])
Beschreibung: Hier ist „results“ ein großes Wörterbuch, „issues“ ist ein Schlüssel in „results“ und der Wert von „issues“ ist eine Liste verschachtelter JSON-Objektwörterbücher. Sie werden die verschachtelte JSON-Struktur später sehen.

Python führt verschachteltes JSON ein, um es in Sekundenschnelle in Dataframe umzuwandeln!Das Problem besteht darin, dass die API eine verschachtelte JSON-Struktur zurückgibt und die Schlüssel, die uns wichtig sind, sich tatsächlich auf verschiedenen Ebenen im Objekt befinden.

Die verschachtelte JSON-Struktur sieht folgendermaßen aus. Und was wir wollen, ist so etwas. Im Folgenden werden die von einer API zurückgegebenen Daten als Beispiel genommen. APIs enthalten normalerweise Metadaten zu verwandten Feldern. Nehmen wir an, das sind die Felder, die wir wollen.

  • Schlüssel: JSON-Schlüssel, auf der ersten Ebene.
  • Zusammenfassung: das „Feld“-Objekt der zweiten Ebene.
  • Statusname: Position der dritten Ebene.
  • statusKategoriename: Befindet sich auf der 4. Verschachtelungsebene.

Wie oben befinden sich die Felder, die wir zum Extrahieren auswählen, nacheinander auf vier verschiedenen Verschachtelungsebenen in der JSON-Struktur in der Problemliste. API和文档数据库会返回嵌套的JSON对象,当我们使用Python尝试将嵌套结构中的键转换为列时,数据加载到pandas中往往会得到如下结果:

{
  "expand": "schema,names",
  "issues": [
    {
      "fields": {
        "issuetype": {
          "avatarId": 10300,
          "description": "",
          "id": "10005",
          "name": "New Feature",
          "subtask": False
        },
        "status": {
          "description": "A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.",
          "id": "5",
          "name": "Resolved",
          "statusCategory": {
            "colorName": "green",
            "id": 3,
            "key": "done",
            "name": "Done",
          }
        },
        "summary": "Recovered data collection Defraglar $MFT problem"
      },
      "id": "11861",
      "key": "CAE-160",
    },
    {
      "fields": { 
... more issues],
  "maxResults": 5,
  "startAt": 0,
  "total": 160
}
说明:这里results是一个大的字典,issues是results其中的一个键,issues的值为一个嵌套JSON对象字典的列表,后面会看到JSON嵌套结构。

问题在于API返回了嵌套的JSON结构,而我们关心的键在对象中确处于不同级别。

嵌套的JSON结构张成这样的。

而我们想要的是下面这样的。

下面以一个API返回的数据为例,API通常包含有关字段的元数据。假设下面这些是我们想要的字段。

  • key:JSON密钥,在第一级的位置。
  • summary:第二级的“字段”对象。
  • status name:第三级位置。
  • statusCategory name:位于第4个嵌套级别。

如上,我们选择要提取的字段在issues列表内的JSON结构中分别处于4个不同的嵌套级别,一环扣一环。

df = (
    df["fields"]
    .apply(pd.Series)
    .merge(df, left_index=True, right_index = True)
)

一个不太好的解决方案

一种选择是直接撸码,写一个查找特定字段的函数,但问题是必须对每个嵌套字段调用此函数,然后再调用.applyDataFrame中的新列。

为获取我们想要的几个字段,首先我们提取fields键内的对象至列:

# 提取issue type的name到一个新列叫"issue_type"
df_issue_type = (
    df["issuetype"]
    .apply(pd.Series)
    .rename(columns={"name": "issue_type_name"})["issue_type_name"]
)
df = df.assign(issue_type_name = df_issue_type)

从上表看出,只有summary是可用的,issuetype、status等仍然埋在嵌套对象中。

下面是提取issuetype中的name的一种方法。

FIELDS = ["key", "fields.summary", "fields.issuetype.name", "fields.status.name", "fields.status.statusCategory.name"]
df = pd.json_normalize(results["issues"])
df[FIELDS]

像上面这样,如果嵌套层级特别多,就需要自己手撸一个递归来实现了,因为每层嵌套都需要调用一个像上面解析并添加到新列的方法。

对于编程基础薄弱的朋友,手撸一个其实还挺麻烦的,尤其是对于数据分析师,着急想用数据的时候,希望可以快速拿到结构化的数据进行分析。

下面东哥分享一个pandas的内置解决方案。

内置的解决方案

pandas中有一个牛逼的内置功能叫 .json_normalize

pandas的文档中提到:将半结构化JSON数据规范化为平面表。

前面方案的所有代码,用这个内置功能仅需要3行就可搞定。步骤很简单,懂了下面几个用法即可。

确定我们要想的字段,使用 . 符号连接嵌套对象。

将想要处理的嵌套列表(这里是results["issues"])作为参数放进 .json_normalize 中。

过滤我们定义的FIELDS列表。

# 使用路径而不是直接用results["issues"]
pd.json_normalize(results, record_path="issues")[FIELDS]

没错,就这么简单。

其它操作

记录路径

除了像上面那样传递results["issues"]列表之外,我们还使用record_path参数在JSON对象中指定列表的路径。

### 用 "-" 替换默认的 "."
FIELDS = ["key", "fields-summary", "fields-issuetype-name", "fields-status-name", "fields-status-statusCategory-name"]
pd.json_normalize(results["issues"], sep = "-")[FIELDS]

自定义分隔符

还可以使用sep参数自定义嵌套结构连接的分隔符,比如下面将默认的“.”替换“-”。

# 只深入到嵌套第二级
pd.json_normalize(results, record_path="issues", max_level = 2)

控制递归

如果不想递归到每个子对象,可以使用max_level参数控制深度。在这种情况下,由于statusCategory.name字段位于JSON对象的第4级,因此不会包含在结果DataFrame中。

rrreee

下面是.json_normalizepandasrrreee

Eine nicht so gute Lösung
🎜🎜Eine Möglichkeit besteht darin, direkt zu codieren und eine Funktion zu schreiben, die nach einem bestimmten Feld sucht. Das Problem besteht jedoch darin, dass diese Funktion für jedes verschachtelte Feld aufgerufen werden muss und dann . Anwenden auf eine neue Spalte in DataFrame. 🎜🎜Um die verschiedenen gewünschten Felder zu erhalten, extrahieren wir zunächst die Objekte in den Feldschlüsseln zu den Spalten: 🎜rrreee🎜Wie aus der obigen Tabelle ersichtlich ist, ist nur eine Zusammenfassung verfügbar, Problemtyp, Status usw. sind immer noch verschachtelt Objekte. 🎜🎜Das Folgende ist eine Methode zum Extrahieren des Namens im Issuetype. 🎜rrreee🎜Wenn wie oben zu viele Verschachtelungsebenen vorhanden sind, müssen Sie die Rekursion selbst implementieren, da jede Verschachtelungsebene eine Methode wie die oben aufgerufene aufrufen muss, um sie zu analysieren und einer neuen Spalte hinzuzufügen. 🎜🎜Für Freunde mit schwachen Programmierkenntnissen ist es tatsächlich ziemlich mühsam, sich eins anzueignen. Besonders für Datenanalysten, die darauf bedacht sind, Daten zu nutzen, hoffen sie, schnell strukturierte Daten für die Analyse zu erhalten. 🎜🎜Jetzt wird Bruder Dong eine integrierte Lösung für Pandas vorstellen. 🎜🎜🎜Integrierte Lösung🎜🎜🎜pandas verfügt über eine tolle integrierte Funktion namens .json_normalize. 🎜🎜In der Dokumentation von pandas wird Folgendes erwähnt: die Normalisierung halbstrukturierter JSON-Daten in eine flache Tabelle. 🎜🎜Der gesamte Code in der vorherigen Lösung kann mit dieser integrierten Funktion in nur 3 Zeilen vervollständigt werden. Die Schritte sind sehr einfach. Verstehen Sie einfach die folgende Verwendung. 🎜🎜Bestimmen Sie die gewünschten Felder und verwenden Sie das Symbol, um verschachtelte Objekte zu verbinden. 🎜🎜Fügen Sie die verschachtelte Liste, die Sie verarbeiten möchten (hier results["issues"]), als Parameter in .json_normalize ein. 🎜🎜Filtern Sie die Liste der von uns definierten FELDER. 🎜rrreee🎜Ja, so einfach ist das. 🎜🎜🎜Andere Vorgänge🎜🎜🎜🎜Pfad aufzeichnen🎜🎜🎜Zusätzlich zur Übergabe der Liste results["issues"] wie oben verwenden wir auch den Parameter record_path JSON-Objekt. 🎜rrreee🎜🎜Benutzerdefiniertes Trennzeichen🎜🎜🎜Sie können den sep-Parameter auch verwenden, um das Trennzeichen für verschachtelte Strukturverbindungen anzupassen. Ersetzen Sie beispielsweise unten den Standardwert „.“ durch „-“. 🎜rrreee🎜🎜Rekursion steuern🎜🎜🎜Wenn Sie nicht zu jedem Unterobjekt rekursieren möchten, können Sie den Parameter max_level verwenden, um die Tiefe zu steuern. Da sich in diesem Fall das Feld statusCategory.name auf Ebene 4 des JSON-Objekts befindet, wird es nicht in den resultierenden DataFrame aufgenommen. 🎜rrreee🎜Das Folgende ist die offizielle Dokumentbeschreibung von pandas für .json_normalize. Wenn Sie es nicht verstehen, können Sie es dieses Mal selbst lernen stellen Sie es hier vor. 🎜🎜Pandas offizielle Dokumentation: https://pandas.pydata.org/pan...🎜

Das obige ist der detaillierte Inhalt vonPython führt verschachteltes JSON ein, um es in Sekundenschnelle in Dataframe umzuwandeln!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn