如何将pandas列内的JSON数据转换为新列

44

我有这份短版的ADSB json数据,希望将其转换为DataFrame列,如Icao、Alt、Lat、Long、Spd、Cou...

在Alperen告诉我之后

df = pd.read_json('2016-06-20-2359Z.json', lines=True), 

我可以将其加载到 DataFrame 中。但是,df.acList 是:

[{'Id': 10537990, 'Rcvr': 1, 'HasSig': False, ...
Name: acList, dtype: object

如何获取 Icao、Alt、Lat、Long、Spd、Cou 数据?

 "src":1,
   "feeds":[  
      {  
         "id":1,
         "name":"ADSBexchange.com",
         "polarPlot":false
      }
   ],
   "srcFeed":1,
   "showSil":true,
   "showFlg":true,
   "showPic":true,
   "flgH":20,
   "flgW":85,
   "acList":[  
      {  
         "Id":11281748,
         "Rcvr":1,
         "HasSig":false,
         "Icao":"AC2554",
         "Bad":false,
         "Reg":"N882AS",
         "FSeen":"\/Date(1466467166951)\/",
         "TSecs":3,
         "CMsgs":1,
         "AltT":0,
         "Tisb":false,
         "TrkH":false,
         "Type":"CRJ2",
         "Mdl":"2001 
BOMBARDIER INC 
 CL-600-2B19",
         "Man":"Bombardier",
         "CNum":"7503",
         "Op":"EXPRESSJET AIRLINES INC - ATLANTA, GA",
         "OpIcao":"ASQ",
         "Sqk":"",
         "VsiT":0,
         "WTC":2,
         "Species":1,
         "Engines":"2",
         "EngType":3,
         "EngMount":1,
         "Mil":false,
         "Cou":"United States",
         "HasPic":false,
         "Interested":false,
         "FlightsCount":0,
         "Gnd":false,
         "SpdTyp":0,
         "CallSus":false,
         "TT":"a",
         "Trt":1,
         "Year":"2001"
      },
      {  
         "Id":11402205,
         "Rcvr":1,
         "HasSig":true,
         "Sig":110,
         "Icao":"ADFBDD",
         "Bad":false,
         "FSeen":"\/Date(1466391940977)\/",
         "TSecs":75229,
         "CMsgs":35445,
         "Alt":8025,
         "GAlt":8025,
         "AltT":0,
         "Call":"TEST1234",
         "Tisb":false,
         "TrkH":false,
         "Sqk":"0262",
         "Help":false,
         "VsiT":0,
         "WTC":0,
         "Species":0,
         "EngType":0,
         "EngMount":0,
         "Mil":true,
         "Cou":"United States",
         "HasPic":false,
         "Interested":false,
         "FlightsCount":0,
         "Gnd":true,
         "SpdTyp":0,
         "CallSus":false,
         "TT":"a",
         "Trt":1
      }
   ],
   "totalAc":4231,
   "lastDv":"636019887431643594",
   "shtTrlSec":61,
   "stm":1466467170029
}
</pre>
5个回答

45
如果您已经在 pandas DataFrame 的 acList 列中拥有数据,则只需执行以下操作即可:
import pandas as pd
pd.io.json.json_normalize(df.acList[0])

Alt AltT    Bad CMsgs   CNum    Call    CallSus Cou EngMount    EngType ... Sqk TSecs   TT  Tisb    TrkH    Trt Type    VsiT    WTC Year
0   NaN 0   False   1   7503    NaN False   United States   1   3   ...     3   a   False   False   1   CRJ2    0   2   2001
1   8025.0  0   False   35445   NaN TEST1234    False   United States   0   0   ... 0262    75229   a   False   False   1   NaN 0   0   NaN

自从pandas 1.0版本以后,导入语句应该为:

import pandas as pd
pd.json_normalize(df.acList[0])

这是在Python 2.7上,对吧?我无法在Python 3上做到这一点。你能帮我吗? - Hamid
@Hamid 这是Python 3。如果你在编码方面遇到问题,请将其发布到SO,并标记为“Pandas”,“json”或其他内容,我们会尽力帮助你。干杯! - Sergey Bushmanov
如果一行或多行有“None”,表示某些记录没有可用数据,该怎么办? - Regressor
@Regressor,您可以通过将None替换为{}来解决问题,可以查看我的答案 - Felipe Augusto

21

@Sergey的回答解决了我的问题,但我遇到了一个问题,因为我的数据框列中的JSON存储为字符串而不是对象。我不得不添加额外的步骤来映射该列:

@Sergey的回答解决了我的问题,但是因为我的数据帧列中的JSON是以字符串形式而不是对象形式保存的,所以我遇到了问题。我不得不添加额外的步骤将该列映射成对象:

import json
import pandas as pd
pd.io.json.json_normalize(df.acList.apply(json.loads))

3
谢谢你帮我处理了这个问题,我的情况是第一列包含JSON数据,我想将它转置到其他列。 - Mantej Singh
这个可以运行,但是如果我有一个要转换成多个的列,同时还有其他正常保留不变的列。我该怎么做呢? - Aly
我不确定,而且我也没有安装pandas环境来检查,但也许你可以搜索一下“flatMap”函数? - ThinkBonobo

7

自从 pandas 1.0 版本以来,json_normalize 已经在顶层命名空间中可用。因此,请使用:

import pandas as pd
pd.json_normalize(df.acList[0])

2

我还不能对ThinkBonobo的回答进行评论,但是如果列中的JSON不完全是字典,您可以继续使用.apply,直到它变成字典为止。所以在我的情况下

import json
import pandas as pd

json_normalize(
    df
    .theColumnWithJson
    .apply(json.loads)
    .apply(lambda x: x[0]) # the inner JSON is list with the dictionary as the only item
)

有用的贡献。 在我的Panda 0.24.2数据中,最后一行不是必需的。 这可能是针对您的数据特定的。例如,我的数据看起来像 {'key':value},也许你的数据看起来像 [{'key':value}]。 - jabberwocky

0
在我的情况下,我有一些缺失值(None),然后我创建了一个更具体的代码,在创建新列后也删除了原始列:
for prefix in ['column1', 'column2']:
    df_temp = df[prefix].apply(lambda x: {} if pd.isna(x) else x)
    df_temp = pd.io.json.json_normalize(df_temp)
    df_temp = df_temp.add_prefix(prefix + '_')
    df.drop([prefix], axis=1, inplace=True)
    df = pd.concat([df, df_temp], axis = 1, sort=False)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接