Pandas数据帧索引匹配

2024-05-21 01:45:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道是否有一种更有效的方法来实现excel中流行的“index&match”类型函数。例如-给定两个pandas数据帧,使用在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中都有大约80000行的数据集,我的目标是在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

Tags: 数据方法函数name类型dataframepandasdf
1条回答
网友
1楼 · 发布于 2024-05-21 01:45:54

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

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转换成一个dict,并用num作为键。map函数从dict的df_1列中查找每个值并返回相应的字母。不需要复杂的索引。

网友
2楼 · 发布于 2024-05-21 01:45:54

高水平

  • 创建要在replace中使用的词典
  • replacerename列和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

分解

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

建筑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楼 · 发布于 2024-05-21 01:45:54

只需尝试一个条件语句:

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

相关问题 更多 >