【问题标题】:Subtracting values from a Pandas Dataframe in an Iterative Fashion以迭代方式从 Pandas 数据框中减去值
【发布时间】:2021-04-16 06:41:58
【问题描述】:

我有一个如下所示的 pandas 数据框。我试图以迭代方式从column A 中的值中减去值1,直到column B 中的值变为0。减法的顺序将通过使用列Sort1Sort2 进行排序来决定以升序方式,首先从 column A row 3 中减去 1,然后再从 column A row 4 中减去 1,最后从 column A 中减去 row 0
我需要对 B 列中存在的每个组分别执行此操作。

Inital DataFrame:

   A  B Sort1  Sort2
0  1  3     A    0.7
1  1  3     B    0.3
2  1  3     C    0.5
3  2  3     A    0.2
4  2  3     A    0.5
5  1  4     A    0.7
6  1  4     B    0.3
7  1  4     C    0.5
8  2  4     A    0.2
9  2  4     A    0.5


Result Dataframe:

   A  B Sort1  Sort2
0  0  0     A    0.7
1  1  0     B    0.3
2  1  0     C    0.5
3  1  0     A    0.2
4  1  0     A    0.5
5  0  0     A    0.7
6  0  0     B    0.3
7  1  0     C    0.5
8  1  0     A    0.2
9  1  0     A    0.5

我可以通过循环遍历数据框来实现这一点,但数据框可能很大,想探索是否有更好的方法来实现这一点?

【问题讨论】:

  • 你不说B列的值是如何变化的还是我遗漏了什么?
  • 基本上,由于 B 列中的值为 3,因此我以我在问题中提到的迭代方式从 A 列中减去 1 三次。希望能提供更多的清晰度。 @divingTobi
  • 但是您也必须对列 B 做一些事情,否则它不会从 3 变为所有条目的 1,不是吗?还是B 列中的所有值始终相同,这基本上是您想要从A 中运行减法的次数?
  • 是的。你说的对。 B 列中的值将始终相同。它基本上是为了跟踪减法需要发生多少次或是否需要发生。所以如果它是 0 基本上我就不需要再做减法了。
  • “迭代减法”与将减法数(在本例中为 -1)乘以 B 列中的值并减去该值不一样吗?所以不是-1,-1,-1,而是-3,应该快3倍。如果您想在低于零时停止减法,请将其写为下限减法函数并应用它。例如lambda x,y : 0 if x<y else x-y 已经定义了该函数,您可以将其作为对不需要循环的数据帧的单个调用来应用。

标签: python pandas dataframe


【解决方案1】:

这是实现相同目的的更短方法,无需遍历组:

import pandas as pd

# df_ = pd.read_clipboard()
df = df_.copy()

s = df.sort_values(by=['Sort1', 'Sort2']).groupby("B", group_keys=False).apply(lambda x: x.head(x.name))['A']-1

df.loc[s.index, "A"] = s

print(df)

导致

   A  B Sort1  Sort2
0  0  3     A    0.7
1  1  3     B    0.3
2  1  3     C    0.5
3  1  3     A    0.2
4  1  3     A    0.5
5  0  4     A    0.7
6  0  4     B    0.3
7  1  4     C    0.5
8  1  4     A    0.2
9  1  4     A    0.5

【讨论】:

    【解决方案2】:

    我不确定这是否真的是您想要的。对于每个组(按B 列),我们选择前 n 个元素(由B 中的值确定),从A 列中减去 1,然后将结果合并回 df。

    import pandas as pd
    
    # df = pd.read_clipboard()
    
    print(df)
    
    gp = df.groupby("B")
    
    s = pd.DataFrame()
    
    for k in gp.groups.keys():
        s = s.append(
            gp.get_group(k).sort_values(by=["Sort1", "Sort2"]).iloc[0:k][["A"]] - 1
        )
    
    print(s)
    
    df2 = df.merge(s, how="left", left_index=True, right_index=True)
    ind = ~df2["A_y"].isna()
    df2.loc[~df2["A_y"].isna(), "A_x"] = df2["A_y"]
    df2 = df2.rename(columns={"A_x": "A"}).drop("A_y", axis=1)
    

    这有点令人费解,但基本上我是按照您的描述对值进行排序,然后选择前 3 列(基于 B 中的值),然后每列减去一个。

    剩下的只是将该新列合并回原始数据框:

         A  B Sort1  Sort2
    0  0.0  3     A    0.7
    1  1.0  3     B    0.3
    2  1.0  3     C    0.5
    3  1.0  3     A    0.2
    4  1.0  3     A    0.5
    5  0.0  4     A    0.7
    6  0.0  4     B    0.3
    7  1.0  4     C    0.5
    8  1.0  4     A    0.2
    9  1.0  4     A    0.5
    

    我没有更改B,因为我不使用它进行迭代。如果需要,您可以将其设置为 0df2['B']=0

    【讨论】:

    • 哦。感谢您的解决方案。我想我现在终于理解了关于 B 栏的困惑。对于那个很抱歉。所以,问题是我可以在同一个数据框中为 B 列设置不同的值集,我需要对 B 列中的每个组分别执行此操作。我会修改问题。
    • 而对于每一组,B中的数字代表次数,应该减去1?
    • 您介意将问题标记为已回答吗?谢谢!
    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 2017-04-15
    • 1970-01-01
    • 2019-02-27
    • 2023-01-14
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    相关资源
    最近更新 更多