如何根据pandas中的条件将列值分配给其他列

时间:2017-07-13 10:47:35

标签: python pandas

我有一个小数据帧。下面给出一个例子。

+-------+---------+---------+------+----------+  
| code  | surplus | deficit | gone | has come |  
+-------+---------+---------+------+----------+
| 0100  |    1000 |       0 |      |          |
| 0103  |       0 |     100 |      |          |
| 0104  |       0 |     600 |      |          |
| 0190  |       0 |       0 |      |          |
| 0191  |       0 |     800 |      |          |
| 0192  |     500 |       0 |      |          |
| 0193  |     700 |       0 |      |          |
| 0194  |       0 |     300 |      |          |
| 0195  |       0 |       0 |      |          |
+-------+---------+---------+------+----------+

我需要分发surplus列中的数据,以涵盖deficit列中的数据。在列gone中,记下我从列surplus中获取的内容,并在列has come中写下我添加了多少来填补这一缺陷。从列surplus开始,随着值的减少,我会获取数据。总是从最大的赤字开始。

在我的例子中,它看起来像这样:

为了弥补最大的赤字(在示例中为800),我将参与价值1000

为了弥补下一个缺陷(在示例中,这是600),我将获取值1000的余数,并从值400中取700。< / p>

为了弥补赤字300,我会使用余下的值700

最后,为了弥补赤字100我参与了价值500

结果应该是下一个数据帧:

+------+---------+---------+------+----------+
| code | surplus | deficit | gone | has come |
+------+---------+---------+------+----------+
| 0100 |    1000 |       0 | 1000 |        0 |
| 0103 |       0 |     100 |    0 |      100 |
| 0104 |       0 |     600 |    0 |      600 |
| 0190 |       0 |       0 |    0 |        0 |
| 0191 |       0 |     800 |    0 |      800 |
| 0192 |     500 |       0 |  100 |        0 |
| 0193 |     700 |       0 |  700 |        0 |
| 0194 |       0 |     300 |    0 |      300 |
| 0195 |       0 |       0 |    0 |        0 |
+------+---------+---------+------+----------+

surplusdeficit列中的值可能不同。

我无法为此任务找到算法。我会很感激任何想法。

2 个答案:

答案 0 :(得分:2)

我害怕我不认识大熊猫所以我不能详细说明答案,但这是一个普遍的算法,我觉得它会很好。你可以将它与pandas API相匹配。

对于“已来”栏目:

  • 按差额(降序)
  • 对条目进行排序
  • 计算此排序列表中的赤字条目的累计总和
  • 用sum(剩余)绑定它,即创建一列max(cumsum(deficit), sum(surplus))
  • 现在用下一个项目来区分每个项目(我认为这是pandas.Series.diff方法?),使用0作为“-1”条目(也许你必须添加一个虚拟行?)。这是你的“来了”价值

对于“来了”栏目(如果sum(surplus) >= sum(deficit)):

  • 在这种情况下,您只需为所有行设置“has come”=“deficit”,这将比上述计算更快
  • 但是如果你没有明确地检查这个案例,上面的计算仍然有效

对于“消失”专栏:只做与上面完全相同的事情,扭转“赤字”和“盈余”。

编辑:在你的例子中,过去的列是棘手的,因为在那种情况下,总和(不足)&lt;总和(盈余)。以上是关于盈余的上述程序。

sum(surplus) = 2200
sum(deficit) = 1800

+------+---------+---------+-----------------+-----------------------------------+----------------+
| code | surplus | deficit | cumsum(surplus) | max(cumsum(surplus),sum(deficit)) | diff(prev row) |
+------+---------+---------+-----------------+-----------------------------------+----------------+
| NaN  |       0 |       0 |               0 |                                 0 |           NaN  |
| 0100 |    1000 |       0 |            1000 |                              1000 |           1000 |
| 0193 |     700 |       0 |            1700 |                              1700 |           700  |
| 0192 |     500 |       0 |            2200 |                              1800 |           100  |
| 0191 |       0 |     800 |            2200 |                              1800 |           0    |
| 0103 |       0 |     100 |            2200 |                              1800 |           0    |
| 0104 |       0 |     600 |            2200 |                              1800 |           0    |
| 0190 |       0 |       0 |            2200 |                              1800 |           0    |
| 0194 |       0 |     300 |            2200 |                              1800 |           0    |
| 0195 |       0 |       0 |            2200 |                              1800 |           0    |
+------+---------+---------+-----------------+-----------------------------------+----------------+

最后一列是您想要的结果。请注意,我在开头添加了一个虚拟行,以便我可以计算成对差异。事实证明shift()是计算该列所需的关键方法;见this question

编辑2:我认为可能值得添加替代解决方案。这有点难以理解,但它可能更容易实现,因为您不需要使用额外的虚拟行。

  • 和以前一样:按缺陷(降序)
  • 对条目进行排序
  • 和以前一样:计算此排序列表中的赤字条目的累计总和
  • 新:找到累积总和大于盈余总和的第一行的索引(我不知道在熊猫中获取此数据是多么容易)。如果没有这样的行,我们称之为ii=Inf。)
  • 对于此索引之前的所有行(即df[:i]),请设置“has come”=“deficit”
  • 对于此索引之后的所有行(即df[i+1:]),请设置“has come”= 0
  • 对于该行(即df[i],如果存在i),请将“已来”设置为:
    • has come = sum(surplus) - (cumsum(deficit) - deficit)
    • (顺便说一句,(cumsum(deficit) - deficit)实际上等于前一行的cumsum(不足),如果这是第一行,则为0。)

答案 1 :(得分:0)

问题“如何根据pandas中的条件将列值分配给其他列?”也许函数 np.where 就是你要找的东西:

import numpy as np
import pandas as pd 

# df[Column title] = np.where ( condition on this line, if condition true then value to assign, else value to assign)
df["gone"] = np.where((df["surplus"] - df["deficit"]) > 0 , df["surplus"] - df["deficit"] , 0)
df["has come"] = np.where((df["surplus"] - df["deficit"]) < 0 , 0, df["deficit"] - df["surplus"] )