【问题标题】:pandas dataframe index match熊猫数据框索引匹配
【发布时间】:2017-11-03 06:28:32
【问题描述】:

我想知道是否有更有效的方法来执行 Excel 中流行的“索引和匹配”类型函数。例如 - 给定两个 pandas DataFrame,使用 df_2 中的信息更新 df_1:

import pandas as pd

df_1 = pd.DataFrame({'num_a':[1, 2, 3, 4, 5],
                     'num_b':[2, 4, 1, 2, 3]})    
df_2 = pd.DataFrame({'num':[1, 2, 3, 4, 5],
                     'name':['a', 'b', 'c', 'd', 'e']})

我正在处理在 df_1 和 df_2 中都有约 80,000 行的数据集,我的目标是在 df_1 中创建两个新列,“name_a”和“name_b”。

以下是我能想到的最有效的方法。 必须有更好的方法!

name_a = []
name_b = []
for i in range(len(df_1)):

    name_a.append(df_2.name.iloc[df_2[
                  df_2.num == df_1.num_a.iloc[i]].index[0]])
    name_b.append(df_2.name.iloc[df_2[
                  df_2.num == df_1.num_b.iloc[i]].index[0]])

df_1['name_a'] = name_a
df_1['name_b'] = name_b

导致:

>>> df_1.head()
   num_a  num_b name_a name_b
0      1      2      a      b
1      2      4      b      d
2      3      1      c      a
3      4      2      d      b
4      5      3      e      c

【问题讨论】:

    标签: python pandas dataframe indexing


    【解决方案1】:

    我认为有一个比已经提供的解决方案更直接的解决方案。既然你提到了 Excel,这是一个基本的 vlookup。您可以在 pandas 中使用Series.map 进行模拟。

    name_map = dict(df_2.set_index('num').name)
    
    df_1['name_a'] = df_1.num_a.map(name_map)
    df_1['name_b'] = df_1.num_b.map(name_map)
    
    df_1
    
       num_a  num_b name_a name_b
    0      1      2      a      b
    1      2      4      b      d
    2      3      1      c      a
    3      4      2      d      b
    4      5      3      e      c
    

    我们所做的只是将 df_2 转换为以 'num' 为键的字典。 map 函数从 dict 的 df_1 列中查找每个值并返回相应的字母。不需要复杂的索引。

    【讨论】:

      【解决方案2】:

      高级

      • 创建字典以在replace 中使用
      • replace、rename 列和 join

      m = dict(zip(
          df_2.num.values.tolist(),
          df_2.name.values.tolist()
      ))
      
      df_1.join(
          df_1.replace(m).rename(
              columns=lambda x: x.replace('num', 'name')
          )
      )
      
         num_a  num_b name_a name_b
      0      1      2      a      b
      1      2      4      b      d
      2      3      1      c      a
      3      4      2      d      b
      4      5      3      5      c
      

      细分

      replace 用字典应该很快。有很多方法可以构建字典表单df_2。事实上,我们可以使用pd.Series。我选择使用dict 和zip 构建,因为我发现它更快。

      大楼m

      选项 1

      m = df_2.set_index('num').name
      

      选项 2

      m = df_2.set_index('num').name.to_dict()
      

      选项 3

      m = dict(zip(df_2.num, df_2.name))
      

      选项 4(我的选择)

      m = dict(zip(df_2.num.values.tolist(), df_2.name.values.tolist()))
      

      m 构建时间

      1000 loops, best of 3: 325 µs per loop
      1000 loops, best of 3: 376 µs per loop
      10000 loops, best of 3: 32.9 µs per loop
      100000 loops, best of 3: 10.4 µs per loop
      
      %timeit df_2.set_index('num').name
      %timeit df_2.set_index('num').name.to_dict()
      %timeit dict(zip(df_2.num, df_2.name))
      %timeit dict(zip(df_2.num.values.tolist(), df_2.name.values.tolist()))
      

      替换num

      再一次,我们有选择,这里有几个和他们的时代。

      %timeit df_1.replace(m)
      %timeit df_1.applymap(lambda x: m.get(x, x))
      %timeit df_1.stack().map(lambda x: m.get(x, x)).unstack()
      
      1000 loops, best of 3: 792 µs per loop
      1000 loops, best of 3: 959 µs per loop
      1000 loops, best of 3: 925 µs per loop
      

      我选择...

      df_1.replace(m)
      
        num_a num_b
      0     a     b
      1     b     d
      2     c     a
      3     d     b
      4     5     c
      

      重命名列

      df_1.replace(m).rename(columns=lambda x: x.replace('num', 'name'))
      
        name_a name_b   <-- note the column name change
      0      a      b
      1      b      d
      2      c      a
      3      d      b
      4      5      c
      

      加入

      df_1.join(df_1.replace(m).rename(columns=lambda x: x.replace('num', 'name')))
      
         num_a  num_b name_a name_b
      0      1      2      a      b
      1      2      4      b      d
      2      3      1      c      a
      3      4      2      d      b
      4      5      3      5      c
      

      【讨论】:

        【解决方案3】:

        试试条件语句:

        import pandas as pd
        import numpy as np
        df_1 = pd.DataFrame({'num_a':[1, 2, 3, 4, 5],
                             'num_b':[2, 4, 1, 2, 3]})    
        df_2 = pd.DataFrame({'num':[1, 2, 3, 4, 5],
                             'name':['a', 'b', 'c', 'd', 'e']})
        df_1["name_a"] = df_2["num_b"]
        df_1["name_b"] = np.array(df_1["name_a"][df_1["num_b"]-1]) 
        print(df_1)
        
           num_a  num_b name_a name_b
        0      1      2      a      b
        1      2      4      b      d
        2      3      1      c      a
        3      4      2      d      b
        4      5      3      e      c
        

        【讨论】:

          猜你喜欢
          • 2022-07-10
          • 2012-11-05
          • 1970-01-01
          • 1970-01-01
          • 2015-05-28
          • 2018-02-02
          • 2012-12-20
          • 2013-08-19
          • 1970-01-01
          相关资源
          最近更新 更多