簡體   English   中英

Pandas DataFrame根據“ id”將jsons列的列表轉換為內容豐富的行

[英]Pandas DataFrame turn a list of jsons column into informative row, per “id”

考慮以下DataFrame:

import pandas as pd

df = pd.DataFrame({'id': [1, 2, 3],
               'json_col': [ [{'aa' : 1, 'ab' : 1}, {'aa' : 3, 'ab' : 2, 'ac': 6}],
                             [{'aa' : 1, 'ab' : 2, 'ac': 1}, {'aa' : 5}],
                             [{'aa': 3, 'ac': 2}] ]})
df
Out[134]: 
   id                                           json_col
0   1  [{'aa': 1, 'ab': 1}, {'aa': 3, 'ab': 2, 'ac': 6}]
1   2           [{'aa': 1, 'ab': 2, 'ac': 1}, {'aa': 5}]
2   3                               [{'aa': 3, 'ac': 2}]

我們可以看到每個ID都有一個json列表。

我想為它的列表中的每個'id'和每個對應的json在DataFrame有一個'row' 因此,以下DataFrame將如下所示:

   id  aa   ab   ac
0   1   1  1.0  NaN
1   1   3  2.0  6.0
2   2   1  2.0  1.0
3   2   5  NaN  NaN
4   3   3  NaN  2.0

我們可以看到,id'1 id '1'在列表中有2個對應的json,因此在新的DataFrame有2行

是否有使用python, panda,numpy或json功能的方法?


添加解決方案的運行時間

setup = """
import pandas as pd
df = pd.DataFrame({'id': [1, 2, 3],
               'json_col': [ [{'aa' : 1, 'ab' : 1}, {'aa' : 3, 'ab' : 2, 'ac': 6}],
                             [{'aa' : 1, 'ab' : 2, 'ac': 1}, {'aa' : 5}],
                             [{'aa': 3, 'ac': 2}] ]})
"""

s1 = """
df = pd.concat(
       [pd.DataFrame(j, index=[i]*len(j)) for i, j in enumerate(df['json_col'], 1)],
       sort=False
     )                             
"""

s2 = """
recs = df.apply(lambda x: [{**{'id': x.id}, **d} for d in x.json_col], axis=1).sum()
df2 = pd.DataFrame.from_records(recs)
"""

%timeit(s1, setup)
52.3 ns ± 2.6 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit(s2, setup)
50.6 ns ± 3.28 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

實現此目的的一種簡短方法是以下方法,盡管我個人並不認為它非常pythonic,因為該代碼有點難以閱讀,並且性能不佳,但是對於小數據處理,這應該可以解決問題:

recs = df.apply(lambda x: [{**{'id': x.id}, **d} for d in x.json_col], axis=1).sum()
df2 = pd.DataFrame.from_records(recs)
# outputs:
   aa   ab   ac  id
0   1  1.0  NaN   1
1   3  2.0  6.0   1
2   1  2.0  1.0   2
3   5  NaN  NaN   2
4   3  NaN  2.0   3

這個怎么運作:

  1. 所應用的lambda通過將{id: x.id}的內容與x.json_col (其中x是一行)的詞典列表中的每個詞典合並來創建新詞典。

  2. 然后將其相加。 由於對元素列表的求和將它們合並為一個大元素列表,因此recs具有以下形式

     [{'id': 1, 'aa': 1, 'ab': 1}, {'id': 1, 'aa': 3, 'ab': 2, 'ac': 6}, {'id': 2, 'aa': 1, 'ab': 2, 'ac': 1}, {'id': 2, 'aa': 5}, {'id': 3, 'aa': 3, 'ac': 2}] 
  3. 然后從記錄中簡單地構造一個新的數據框。

這是通過將所有json_col字典列表轉換為DataFrame並將它們串聯在一起以及一些調整來創建id列的一種快速方法:

In [51]: df = pd.concat(
           [pd.DataFrame(j, index=[i]*len(j)) for i, j in enumerate(json_col, 1)],
           sort=False
         )

In [52]: df.index.name = 'id'

In [53]: df.reset_index()
Out[53]: 
   id  aa   ab   ac
0   1   1  1.0  NaN
1   1   3  2.0  6.0
2   2   1  2.0  1.0
3   2   5  NaN  NaN
4   3   3  NaN  2.0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM