繁体   English   中英

如何向 dataframe (df1) 添加一个新列,这是另一个 dataframe (df2) 中 df1 的多个查找值的总和

[英]How can I add a new column to a dataframe (df1) that is the sum of multiple lookup values from df1 in another dataframe (df2)

假设我有 2 个数据框:

df1

     id       guid               name      item1        item2        item3        item4        item5         item6       item7        item8       item9
0  3031958124  85558-261955282  Alonso  85558-57439  85558-54608  85558-91361  85558-40647  85558-41305  85558-79979  85558-33076  85558-89956  85558-12554
1  3031958127  85558-261955282  Jeff    85558-57439  85558-39280  85558-91361  85558-55987  85558-83083  85558-79979  85558-33076  85558-41872  85558-12554
2  3031958129  85558-261955282  Mike    85558-57439  85558-39280  85558-91361  85558-55987  85558-40647  85558-79979  85558-33076  85558-88297  85558-12534
...

df2 其中item_lookup是索引

             item_type   cost  value  target 
item_lookup
85558-57439  item1       9500   25.1   1.9
85558-54608  item2       8000   18.7   0.0 
85558-91361  item3       7000   16.5   0.9
...

我想使用 item_lookup ( df2 ) 为每个 item1 到 item9 添加costvaluetarget的总和,并将其存储为 df1 上的列。

所以结果应该是这样的:df1

     id       guid               name      item1        item2        item3        item4        item5         item6       item7        item8       item9       cost   value  target
0  3031958124  85558-261955282  Alonso  85558-57439  85558-54608  85558-91361  85558-40647  85558-41305  85558-79979  85558-33076  85558-89956  85558-12554  58000   192.5   38.3
1  3031958127  85558-261955282  Jeff    85558-57439  85558-39280  85558-91361  85558-55987  85558-83083  85558-79979  85558-33076  85558-41872  85558-12554  59400   183.2   87.7
2  3031958129  85558-261955282  Mike    85558-57439  85558-39280  85558-91361  85558-55987  85558-40647  85558-79979  85558-33076  85558-88297  85558-12534  58000   101.5   18.1
...

我尝试过使用.map在线遵循类似的解决方案,但是这些示例仅适用于单列,而我试图对 9 列的值求和。

您可以通过使用df.apply来做到这一点,基本上循环遍历行,然后循环遍历行中的项目并计算总和


因为我不能使用你的 dfs 因为它们不完整,所以我做了我的。

给定df1

  item1 item2 item3
0     b     e     j
1     d     a     d
2     j     b     a
3     c     j     f
4     e     f     c
5     a     d     b
6     f     c     e

df2

             cost  value  target
item_lookup                     
a              19     20      12
b              16     14      14
c              20     18      18
d              17     12      14
e              20     15      17
f              19     20      12
j              11     17      12

您可以使用以下 function 来获得您需要的东西

def add_items(row):
     row["cost"] = row["target"] = row["value"] = 0
     # get the columns that have item in the name
     cols = [col for col in df1.columns if "item" in col]
     # get each of the columns look it up in df2 and add it to our new cols
     for col in cols:
         item_lookup = row[col]
         lookup_result = df2.loc[item_lookup]
         row["cost"] += lookup_result["cost"]
         row["target"] += lookup_result["target"]
         row["value"] += lookup_result["value"]
     return row

然后应用它

>>> df1.apply(add_items, axis=1)
  item1 item2 item3  cost  target  value
0     b     e     j    47      43     46
1     d     a     d    53      40     44
2     j     b     a    46      38     51
3     c     j     f    50      42     55
4     e     f     c    59      47     53
5     a     d     b    52      40     46
6     f     c     e    59      47     53

我在这里得到了一个更简单的解决方案。 首先,将 cost、target 和 value 对应的item_lookup值保存到字典中。 然后使用.map().sum()创建列:

df2.reset_index(drop=False, inplace=True)

map_cost = dict(zip(df2['item_lookup'], df2['cost']))
map_value = dict(zip(df2['item_lookup'], df2['value']))
map_target = dict(zip(df2['item_lookup'], df2['target']))


df1['cost'] = df1.apply(lambda x: x.map(map_cost)).sum(axis=1)
df1['value'] = df1.apply(lambda x: x.map(map_value)).sum(axis=1)
df1['target'] = df1.apply(lambda x: x.map(map_target)).sum(axis=1)


df1

Output:

           id             guid    name        item1        item2        item3     cost  value  target
0  3031958124  85558-261955282  Alonso  85558-57439  85558-54608  85558-91361  24500.0   60.3     2.8
1  3031958127  85558-261955282    Jeff  85558-57439  85558-39280  85558-91361  16500.0   41.6     2.8
2  3031958129  85558-261955282    Mike  85558-57439  85558-39280  85558-91361  16500.0   41.6     2.8

我更喜欢以下解决方案,它具有@ali bakhtiari 和@zaki98 提出的解决方案的元素,但更加明确、高效和灵活。 使用applymap因为项目查找对于所有项目列都是相同的,假设df2中的item_lookup唯一标识每一行(所有解决方案都假设这一点); 但是,我提出的解决方案还处理df1中不存在的item_lookup的情况df2 对于df1和 `df2 如下,

df1

DF2

将列定义为 sum、 sum_colsdf1中的 item 列、 item_cols ,然后 append 将每个求和列定义为df1 ,如下所示:

sum_cols = ['cost', 'value', 'target']
item_cols = [col for col in df1.columns if 'item' in col]

df2.set_index('item_lookup', inplace=True)
for sc in sum_cols:
    df1[sc] = df1[item_cols] \
                    .applymap(lambda x: df2.at[x, sc] if x in df2.index else 0) \
                    .sum(axis=1)

这个问题似乎也是 over loc性能at的一个很好的用例,因为每次只查找一个数值(参见这篇SO 帖子)。 没有必要将item_lookup设置为df2上的索引,但这样做应该会提高大型数据集的性能。 如果df1中的item_lookup不存在于df2中,您也可以替换为NaN ,例如,这样可以计算缺少的item_lookup值的数量,而额外的工作量最少。

Output df1 :

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM