【问题标题】:Fastest Way to fill values of a dataframe using .loc from another multi-indexed dataframe使用来自另一个多索引数据帧的 .loc 填充数据帧值的最快方法
【发布时间】:2018-04-26 05:27:38
【问题描述】:

我有一个数据框df1

key1    key2   val
1       100     
2       500   
4       400 

我还有一个多索引数据框df2

       c
a  b     
1 100  a
2 200  b
3 300  j
4 400  e
5 500  t

我想从多索引数据框 df2

中填充我的 df1 的列 val

我试过了:

for index,row in df1.iterrows():
    try:
        data = df2.loc([row['key1'],row['key2'])
        df1.loc[(df1.key1 == row['key1']) & (df1.key2 == row['key2']), 'val'] = data
    except:
        pass

最后,我的 df1 应该是这样的:

key1    key2   val
1       100     a
2       500   
4       400     e

但我主要担心的是 df2(multi-indexed df) 的实际长度将在 60-70 千行左右。

df1 的长度几乎不会是 10 行。 (我想重复这个过程,获取包含其他数据的 df1)

所以这个 .loc 使用 for 循环工作吗?它是最快的吗?

或者使用 .apply 会更快?

我希望这次迭代最快。

关于以尽可能快的方式运行的任何线索?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    在 pandas 中最好避免 loopss - iterrowsapply(引擎盖下的循环),更好的是矢量化解决方案。

    join与参数on一起使用:

    #for improve performance sort index and columns
    df2 = df2.sort_index()
    df1 = df1.sort_values(['key1','key2'])
    
    df = df1.join(df2, on=['key1','key2'])
    print (df)
       key1  key2  val    c
    0     1   100  NaN    a
    1     2   500  NaN  NaN
    2     4   400  NaN    e
    

    编辑:

    另一种方法是加入MultiIndex 和列值并使用map

    df2.index = ['{}_{}'.format(a,b) for a, b in df2.index]
    print (df2)
           c
    1_100  a
    2_200  b
    3_300  j
    4_400  e
    5_500  t
    
    df1['joined'] = df1['key1'].astype(str) + '_' + df1['key2'].astype(str)
    print (df1)
       key1  key2  val joined
    0     1   100  NaN  1_100
    1     2   500  NaN  2_500
    2     4   400  NaN  4_400
    
    df1['col'] = df1['joined'].map(df2['c'])
    print (df1)
       key1  key2  val joined  col
    0     1   100  NaN  1_100    a
    1     2   500  NaN  2_500  NaN
    2     4   400  NaN  4_400    e
    

    时间安排

    np.random.seed(123)
    N = 100000
    df2 = pd.DataFrame(np.random.randint(10000, size=(N, 3)), columns=list('abc'))
    df2 = df2.drop_duplicates(['a','b']).set_index(['a','b'])
    print (df2.head())
                  c
    a    b         
    3582 1346  5218
    7763 9785  7382
    5857 96    6257
    6782 4143  4169
    5664 942   6368
    
    df1 = df2.iloc[np.random.randint(N, size=10)].reset_index()
    df1.columns = ['key1','key2','val']
    print (df1)
       key1  key2   val
    0  5157  9207   283
    1  6452  6474  7092
    2  1264  5009  5123
    3    86  7225  1025
    4  7787  5134   637
    5  9406  6119  8719
    6  7479  1493  1525
    7  4098  7248  7618
    8  9921  7925  8547
    9  2320   764  1564
    

    1.加入未排序的MultiIndex,列:

    In [42]: %timeit df1.join(df2, on=['key1','key2'])
    100 loops, best of 3: 11.1 ms per loop
    

    2.先排序后加入(排序中不使用排序):

    df2 = df2.sort_index()
    
    In [44]: %timeit df1.join(df2, on=['key1','key2'])
    100 loops, best of 3: 10.5 ms per loop
    

    3.map 解决方案,也加入MultiIndex 不计入计时,如果仍然相同的数据只运行一次:

    df2.index = ['{}_{}'.format(a,b) for a, b in df2.index]
    df1['joined'] = df1['key1'].astype(str) + '_' + df1['key2'].astype(str)
    
    In [51]: %timeit df1['col'] = df1['joined'].map(df2['c'])
    1000 loops, best of 3: 371 µs per loop
    

    In [55]: %%timeit
        ...: df1['joined'] = df1['key1'].astype(str) + '_' + df1['key2'].astype(str)
        ...: df1['col'] = df1['joined'].map(df2['c'])
        ...: 
    1000 loops, best of 3: 1.08 ms per loop
    

    【讨论】:

    • 加入 df1(非常小的 df)和 df2(非常大的尺寸)会导致任何性能问题吗?还。把 Na 换成 0 也是可以的吧?
    • @Shubham - 我认为join 作为循环解决方案更好,将NaNs 替换为0 使用df['c'] = df['c'].fillna(0)
    • :) 很好,只是出于对所有三种方法的好奇,哪种方法最快?
    • 谢谢,即使我正在运行 %timeit :)
    【解决方案2】:

    我认为这不是fill value 问题,而是filter index 问题。试试下面:

    df1 = df1.set_index(["key1", "key2"])
    result = df2.loc[df1.index, :].reset_index()
    

    如果你想保留原来的列:

    result.columns=["key1", "key2", "val"]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-31
      • 2021-12-25
      • 2021-01-11
      • 2018-07-15
      • 2013-08-13
      • 2021-09-22
      • 2021-09-04
      • 2019-08-20
      相关资源
      最近更新 更多