【问题标题】:How to merge two unequal rows of a pandas dataframe, where one column value is to match and another column is to be added?如何合并熊猫数据框的两个不相等的行,其中一个列值要匹配,而另一列要添加?
【发布时间】:2021-10-13 11:35:07
【问题描述】:

我给出了以下熊猫数据框:

    d = {'ID': ['1169', '1234', '2456', '9567', '1234', '4321', '9567', '0169'], 'YEAR': ['2001', '2013', '2009', '1989', '2012', '2013', '2002', '2012'], 'VALUE': [8, 24, 50, 75, 3, 6, 150, 47]}
    df = pd.DataFrame(data=d)
    print(df)

         ID  YEAR  VALUE
    0  1169  2001      8
    1  1234  2013     24
    2  2456  2009     50
    3  9567  1989     75
    4  1234  2012      3
    5  4321  2013      6
    6  9567  2002    150
    7  1169  2012     47

我现在想合并两行 DataFrame,其中有两个不同的 ID,最终只剩下一个。仅当“YEAR”列的值匹配时才应进行合并。应添加“VALUE”列的值。

输出应如下所示:

         ID  YEAR  VALUE
    0  1169  2001      8
    1  1234  2013     30
    2  2456  2009     50
    3  9567  1989     75
    4  1234  2012      3
    5  9567  2002    150
    6  1169  2012     47

第 1 行和第 5 行已合并。第 5 行已删除,第 1 行仍保留之前的 ID,但已添加第 1 行和第 5 行的 VALUE。

我想稍后指定应该合并哪两行或哪两个 ID。两者之一应始终保留。要合并的两个 ID 来自另一个函数。

我尝试了 groupby() 函数,但我不知道如何在那里合并两个不同的 ID。我只使用“ID”列的相同值来管理它。然后看起来像这样:

    df.groupby(['ID', 'YEAR'])['VALUE'].sum().reset_index(name ='VALUE')

不幸的是,即使经过大量搜索,我也没有找到任何合适的东西。如果有人可以帮助我,我会很高兴!我想稍后将整个内容应用于具有更多行的更大的 DataFrame。提前致谢并致以最诚挚的问候!

【问题讨论】:

  • 所以换句话说,第二个 ID (4321) 应该在输出中被抑制,有利于胜过 1234。算法应该如何决定结果是哪个 ID?
  • @hc_dev 我将从另一个函数中手动传递两个要合并的 ID!也许可以指定应该留下传递的第一个ID?我对想法持开放态度!
  • @hc_dev 后面的DataFrame会有几千行,有很多不同的ID,两个不同的ID总是要合并的,它们的位置是随机的。

标签: python pandas dataframe replace merge


【解决方案1】:

根据所有 cmets 并更新到问题,听起来需要 逻辑(可能不是 这个确切的代码)...

试试:

import pandas as pd

d = {'ID': ['1169', '1234', '2456', '9567', '1234', '4321', '9567', '0169'], 'YEAR': ['2001', '2013', '2009', '1989', '2012', '2013', '2002', '2012'], 'VALUE': [8, 24, 50, 75, 3, 6, 150, 47]}

df = pd.DataFrame(d)

df['ID'] = df['ID'].astype(int)

def correctRows(l, i):
    for x in l:
        if df.loc[x, 'YEAR'] == df.loc[i, 'YEAR']:
            row = x
            break
    return row

def mergeRows(a, b):
    rowa = list(df[df['ID'] == a].index)
    rowb = list(df[df['ID'] == b].index)
    if len(rowa) > 1:
        if type(rowb)==list:
            rowa = correctRows(rowa, rowb[0])
        else:
            rowa = correctRows(rowa, rowb)
    else:
        rowa = rowa[0]
    
    if len(rowb) > 1:
        if type(rowa)==list:
            rowb = correctRows(rowb, rowa[0])
        else:
            rowb = correctRows(rowb, rowa)
    else:
        rowb = rowb[0]
        
    print('Keeping:', df.loc[rowa].to_string().replace('\n', ', ').replace('     ', ' '))
    print('Dropping:', df.loc[rowb].to_string().replace('\n', ', ').replace('     ', ' '))
    
    
    df.loc[rowa, 'VALUE'] = df.loc[rowa, 'VALUE'] + df.loc[rowb, 'VALUE']
    df.drop(df.index[rowb], inplace=True)
    df.reset_index(drop = True, inplace=True)
    return None

# add two ids.  First 'ID' is kept; the second dropped, but the 'Value'
# of the second is added to the 'Value' of the first.
# Note: the line near the start df['ID'].astype(int), hence integers required

# mergeRows(4321, 1234)

mergeRows(1234, 4321)

输出:

 Keeping: ID   1234, YEAR 2013, VALUE  24
Dropping: ID   4321, YEAR 2013, VALUE   6

框架现在看起来像:

ID  YEAR    VALUE
0   1169    2001    8
1   1234    2013    30  #<-- sum of 6 + 24
2   2456    2009    50
3   9567    1989    75
4   1234    2012    3
5   9567    2002    150
6   169     2012    47

【讨论】:

  • 非常感谢!你是我的英雄。 (也再次感谢所有尝试提供解决方案的人)。
【解决方案2】:

试试这个,只需对“ID”进行分组,然后取最大 YEAR 和总和 VALUE:

df.groupby('ID', as_index=False).agg({'YEAR':'max', 'VALUE':'sum'})

输出:

     ID  YEAR  VALUE
0  1234  2013     27
1  4321  2013      6

或按年份分组并获取第一个 ID:

df.groupby('YEAR', as_index=False).agg({'ID':'first', 'VALUE':'sum'})

输出:

   YEAR    ID  VALUE
0  2012  1234      3
1  2013  1234     30

【讨论】:

  • 首先,感谢您的快速努力!!!第二个输出已经朝着正确的方向发展。但是,我的目标是在一个 DataFrame 中合并两行,其中包含超过 10 000 行。这样做时,要合并的两行将随机位于某处。您对此有解决方案吗?可能我的例子太简单了,抱歉。
  • @Alfonso 使用 pd.concat 这个 groupby 的结果和原始数据框,所以结果在底部。
  • 这样的问题是不能选择合并哪两个ID,留下哪个?您确实必须在具有许多行和许多不同 ID(和 YEAR)的 DF 中想象这一点。我想指定合并哪两个ID,留下哪两个。
  • 对不起@Alfonso,我不太明白。你能让你的测试用例更复杂并显示预期的输出吗?
  • 我已经把这个例子变得更复杂了,谢谢你的提示。我希望你现在能更好地理解它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-20
  • 2022-01-23
  • 1970-01-01
  • 2021-05-15
  • 2017-08-02
  • 1970-01-01
  • 2017-12-08
相关资源
最近更新 更多