根据上一列中的值在 Python Dataframe 中构建行

Posted

技术标签:

【中文标题】根据上一列中的值在 Python Dataframe 中构建行【英文标题】:Build rows in Python Dataframe, based on values in previous column 【发布时间】:2020-05-21 04:37:21 【问题描述】:

我的输入如下所示:

import datetime as dt
import pandas as pd

some_money = [34,42,300,450,550]
df = pd.DataFrame('TIME': ['2020-01', '2019-12', '2019-11', '2019-10', '2019-09'], \
                    'MONEY':some_money) 
df

产生以下内容:

我想再添加 3 列,获取上个月的 MONEY 值,如下所示(颜色编码用于说明目的):

这是我尝试过的:

prev_period_money = ["m-1", "m-2", "m-3"]
for m in prev_period_money:
    df[m] = df["MONEY"] - 10 #well, it "works", but it gives df["MONEY"]- 10...

TIME 列已排序,因此不必关心它。 (但如果有人展示“魔法”,能够从中获取数据,那就太好了。)

【问题讨论】:

【参考方案1】:

用于pandas 0.24+ fill_value=0 in Series.shift,然后也是正确的整数列:

for x in range(1,4):
    df[f"m-x"] = df["MONEY"].shift(periods=-x, fill_value=0)

print (df)
      TIME  MONEY  m-1  m-2  m-3
0  2020-01     34   42  300  450
1  2019-12     42  300  450  550
2  2019-11    300  450  550    0
3  2019-10    450  550    0    0
4  2019-09    550    0    0    0

对于低于 0.24 的 pandas,需要替换缺失值并转换为整数:

for x in range(1,4):
    df[f"m-x"] = df["MONEY"].shift(periods=-x).fillna(0).astype(int)

【讨论】:

语法短得多。 每列的fillna(0) 实际上是相当重要的,否则df = df.fillna(0) 可能会“污染”整个表格。【参考方案2】:

如果你使用shift就很简单

这会给你想要的输出:

df["m-1"] = df["MONEY"].shift(periods=-1)
df["m-2"] = df["MONEY"].shift(periods=-2)
df["m-3"] = df["MONEY"].shift(periods=-3)
df = df.fillna(0)

这只有在订购时才有效。否则,您必须先订购。

【讨论】:

如果您知道“移位”存在......我期待“偏移”作为一个术语。 :) 谢谢 :) @Vityata 这是真的。知识就是力量。顺便说一句,你也可以将它集成到你的 for 循环中,而不是三行。【参考方案3】:

我的建议:使用带有 shift 函数的列表推导来获取三列,将它们连接到列上,然后再次将其连接到原始数据帧

(pd.concat([df,pd.concat([df.MONEY.shift(-i) for i in 
                         range(1,4)],axis=1)],
           axis=1)
  .fillna(0)
 )


    TIME    MONEY   MONEY   MONEY   MONEY
0   2020-01 34  42.0    300.0   450.0
1   2019-12 42  300.0   450.0   550.0
2   2019-11 300 450.0   550.0   0.0
3   2019-10 450 550.0   0.0 0.0
4   2019-09 550 0.0 0.0 0.0

【讨论】:

【参考方案4】:
import pandas as pd

columns = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov"]
some_money = [34,42,300,450,550]

df = pd.DataFrame('TIME': ['2020-01', '2019-12', '2019-11', '2019-10', '2019-09'], 'MONEY':some_money)

prev_period_money = ["m-1", "m-2", "m-3"]
count = 1
for m in prev_period_money:
    df[m] = df['MONEY'].iloc[count:].reset_index(drop=True)
    count += 1

df = df.fillna(0)

输出:

      TIME  MONEY    m-1    m-2    m-3
0  2020-01     34   42.0  300.0  450.0
1  2019-12     42  300.0  450.0  550.0
2  2019-11    300  450.0  550.0    0.0
3  2019-10    450  550.0    0.0    0.0
4  2019-09    550    0.0    0.0    0.0

【讨论】:

索引的删除和重置是什么概念? @Vityata iloc 正在收集带有原始索引的行

以上是关于根据上一列中的值在 Python Dataframe 中构建行的主要内容,如果未能解决你的问题,请参考以下文章

如何根据列渲染器中的值在网格列中显示图像?

将双引号添加到列中的值,只要值在数据框中有引号

当不同列中的值在两个值之间时,Python需要获取一列数据的平均值或平均值

迭代数据框并根据一列的值在具有前一行值的新列中执行操作

如果列中的值在一组值列表中,则过滤数据框行[重复]

Python Pandas根据多个其他列中的条件替换一列中的值[重复]