簡體   English   中英

將大字典轉換為數據框的最快方法

[英]Fastest way to convert huge dictionary to a dataframe

我有一本看起來像這樣的字典:

dict = {A: {A: 0,
  B: 1,
  C: 1,
  D: 2,
  E: 2,
  F: 2,
  G: 2,
  H: 2,
  I: 3},
 B: {B: 0,
  A: 1,
  K: 1,
  O: 1,
  M: 1,
  Q: 1,
  L: 1,
  Z: 2,
  T: 2},
 C: {C: 0,
  R: 1,
  A: 1,
  D: 2,
  F: 2,
  J: 2,
  E: 2,
  Y: 2,
  B: 2},
 D: {D: 0,
  F: 1,
  H: 1,
  I: 1,
  E: 1,
  A: 2,
  C: 2,
  S: 2,
  U: 3}

但實際上它更大(最多 60K 個鍵),我需要一種非常快速有效的方法來將此字典轉換為如下所示的數據框:

person_1     person_2    degree
   A            A          0
   A            B          1 
   A            C          1
   A            D          2
   A            E          2 
   A            F          2
   A            G          2
   A            H          2 
   A            I          3
   B            B          0
   B            A          1 
   B            K          1 
   B            O          1
   B            M          1 
   B            Q          1 
   B            L          1
   B            Z          2 
   B            T          2 
   C            C          0
   C            R          1 
   C            A          1 
   C            D          2
   C            F          2 
   C            J          2 
   C            E          2
   C            Y          2 
   C            B          2
   D            D          0
   D            F          1 
   D            H          1 
   D            I          1
   D            E          1 
   D            A          2 
   D            C          2
   D            S          2 
   D            U          3

所以基本上我需要一個數據框,每個數據框都來自字典鍵及其值,第三列是該鍵內的數字。 我現在正在做的是使用df = pd.DataFrame(dict)將字典轉換為 df 然后

df = pd.melt(df, 'index').rename(columns = {'index': 'hcp_npi', 
                                            'variable':'connected_hcp_npi', 
                                            'value': 'degree_of_separation'}).dropna()

我得到了我需要的結果。 但是這種方法的問題在於,當字典超過 20K 鍵時,melt 函數需要永遠運行。 所以我正在尋找一種更快或更有效的方法來從初始字典到最后一個數據幀。

謝謝!

將字典預處理為列值似乎更快:

from collections import defaultdict

d2 = defaultdict(list)
for k, v in d.items():
    d2['person_1'] += [k] * len(v)
    d2['person_2'] += list(v.keys())
    d2['degree'] += list(v.values())

df = pd.DataFrame(d2)

我測試了你的方法,@jezrael,@BENYs(現已刪除)和我的使用timeit和這樣的代碼(根據需要替換stmt ):

timeit.timeit(setup='''
import pandas as pd
d = {'A': {'A': 0, 'B': 1, 'C': 1, 'D': 2, 'E': 2, 'F': 2, 'G': 2, 'H': 2, 'I': 3},
 'B': {'B': 0, 'A': 1, 'K': 1, 'O': 1, 'M': 1, 'Q': 1, 'L': 1, 'Z': 2, 'T': 2},
 'C': {'C': 0, 'R': 1, 'A': 1, 'D': 2, 'F': 2, 'J': 2, 'E': 2, 'Y': 2, 'B': 2},
 'D': {'D': 0, 'F': 1, 'H': 1, 'I': 1, 'E': 1, 'A': 2, 'C': 2, 'S': 2, 'U': 3}
 }
''',
stmt='''
df = pd.DataFrame(d)
df = pd.melt(df).rename(columns = {'index': 'hcp_npi', 
                                            'variable':'connected_hcp_npi', 
                                            'value': 'degree_of_separation'}).dropna()
''',
number=1000)

對於 1000 次迭代,結果為:

Nick      0.2878
jezrael   0.3178
BENY      2.2822
TomasCB   2.2774

作為參考,我在此處包含@BENY 答案:

pd.concat({x : pd.Series(y) for x , y in d.items()}).reset_index()

對元組列表使用具有展平值的列表推導,然后傳遞給 DataFrame 構造函數:

df = pd.DataFrame([(k, k1, v1) for k, v in d.items() for k1, v1 in v.items()], 
                  columns=['person_1','person_2','degree'])

print (df)
   person_1 person_2  degree
0         A        A       0
1         A        B       1
2         A        C       1
3         A        D       2
4         A        E       2
5         A        F       2
6         A        G       2
7         A        H       2
8         A        I       3
9         B        B       0
10        B        A       1
11        B        K       1
12        B        O       1
13        B        M       1
14        B        Q       1
15        B        L       1
16        B        Z       2
17        B        T       2
18        C        C       0
19        C        R       1
20        C        A       1
21        C        D       2
22        C        F       2
23        C        J       2
24        C        E       2
25        C        Y       2
26        C        B       2
27        D        D       0
28        D        F       1
29        D        H       1
30        D        I       1
31        D        E       1
32        D        A       2
33        D        C       2
34        D        S       2
35        D        U       3

外鍵和內鍵的 50k 獨特組合的性能:

np.random.seed(20)


from collections import defaultdict


df = pd.DataFrame({'a': np.random.randint(100, size=50000),
                  'b': np.random.randint(500000000, size=50000),
                  'c': np.random.randint(20, size=50000)}).sort_values(['a','b']).drop_duplicates(['a','b'])

df[['a','b']] = 'a' + df[['a','b']].astype(str)

s = df.set_index(['a','b'])['c']
print (s)
a    b         
a0   a87201         6
     a1392645      12
     a1428929       9
     a2453757       8
     a2467544      14
                   ..
a99  a496111083    15
     a496689150     6
     a497489331     3
     a499160652    15
     a499359212     0
Name: c, Length: 50000, dtype: int32

d = {level: s.xs(level).to_dict() for level in s.index.levels[0]}


In [210]: %%timeit
     ...: d2 = defaultdict(list)
     ...: for k, v in d.items():
     ...:     d2['person_1'] += [k] * len(v)
     ...:     d2['person_2'] += list(v.keys())
     ...:     d2['degree'] += list(v.values())
     ...: 
     ...: pd.DataFrame(d2)
     ...: 
     ...: 
21.2 ms ± 478 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [211]: %%timeit
     ...: pd.DataFrame([(k, k1, v1) for k, v in d.items() for k1, v1 in v.items()], columns=['person_1','person_2','degree'])
     ...: 
     ...: 
25.8 ms ± 119 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [212]: %%timeit
     ...: pd.concat({x : pd.Series(y) for x , y in d.items()}).reset_index()
     ...: 
110 ms ± 3.68 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [213]: %%timeit
     ...: df = pd.DataFrame(d)
     ...: pd.melt(df).rename(columns = {'index': 'hcp_npi',  'variable':'connected_hcp_npi', 'value': 'degree_of_separation'}).dropna()
     ...: 
1.17 s ± 7.81 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

暫無
暫無

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

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