如果以后在 python (pandas) 中出现相同的值,则为虚拟

Posted

技术标签:

【中文标题】如果以后在 python (pandas) 中出现相同的值,则为虚拟【英文标题】:Dummy if the same value occurs on a later date in python (pandas) 【发布时间】:2021-09-04 22:34:22 【问题描述】:

我有一个df,其中包含每个名称的多个连续日期(yyyy-mm-dd),其中包含该名称出现的几个连续日期(yyyy-mm-dd)。我想在新列Rep 中创建一个虚拟变量,指示相同名称是否在以后再次出现。 我想过循环遍历NameDate 这两列,这样对于每个具有最年轻日期的名称都设置一个0,而对于所有其他名称设置一个1。 此外,我尝试使用duplicated,但由于同一个Name 多次出现在同一个Date 上,此方法不提供目标输出。

df:

Name    Date
A       2006-01-01
B       2006-01-02
A       2006-01-04
A       2006-01-04
B       2006-01-08

结果df:

Name    Date           Rep
A       2006-01-01     1
B       2006-01-02     1
A       2006-01-04     0
A       2006-01-04     0
B       2006-01-08     0

带有duplicated方法的代码:

df = df(by=["Name", "Date"])
df["Rep"] = df.duplicated(subset=["Name", "Date"], keep = "last")

取得的成果:

Name    Date           Rep
A       2006-01-01     1
B       2006-01-02     1
A       2006-01-04     1 # this should be 0!
A       2006-01-04     0
B       2006-01-08     0

根据需要,一个 csv 文件的样本:

Name;Date;Name_Parent;Amount_Est
A;2006-01-01;3;646,200.00
B;2006-01-02;2;25,000,000.00
A;2006-01-04;3;18,759,000.00
A;2006-01-04;5;18,759,000.00
C;2006-01-04;4;18,759,000.00
B;2006-01-08;6;945,000.00
C;2006-01-09;2;945,000.00
A;2006-01-10;4;945,000.00

为了创建df,我使用了熊猫。 因为我有 40 个单一的 csv 文件,所以我使用了一个循环:

import pandas as pd
import glob2 as glob

# import and merge data
path = r'/Users/...'
all = glob.glob(path + "/*.csv")

l = []

for f in all:
    df1 = pd.read_csv(f, sep =";", index_col = None, header = 0)
    df1 = df1.drop(df1.index[0])
    l.append(df1)

df = pd.concat(l, axis = 0)
del f, all, df1, l, path

感谢您的帮助!

【问题讨论】:

上传数据集的样本(不是全部)(例如源/输入 csv 文件)以及用于从数据集创建 df 的代码。那么,我可以帮你。 @Joshua,对不起,我是新手,所以我真的不知道你需要什么。我读到无法将文件上传到 SO。但我有一个看起来像上面的 csv 文件。导入后,目前无需进一步编码。 您可以在此处粘贴一小块 csv/样本(以代码格式)。或者,您可以在谷歌驱动器等外部网站中链接到它。我的意思是你用来生成数据框的代码。就像有几个用于从 csv 生成数据帧的 python 库一样,解决方案可能会因您使用的库而异。如果可能,也包括链接到 csv 文件的行,而不仅仅是库的名称。 ***.com/help/minimal-reproducible-example 是的,它有帮助。我在下面回答了你的问题。让我知道它是否是您正在寻找的。​​span> 【参考方案1】:

这是示例输出:

代码如下:

import pandas as pd
import glob
from shutil import copyfile
import os
def file_len(fname):
    with open(fname) as fp:
        for i, line in enumerate(fp):
            pass
    return i + 1
def read_nth(fname,intNth):
    with open(fname) as fp:
        for i, line in enumerate(fp):
            if i == (intNth-1):
                return line
def showRepetitions(fname):
    temp8 = []
    temp3 = []
    for temp1 in range(file_len(fname),-1,-1):
        if "Name;Date;Name_Parent;Amount_Est" in read_nth(fname,temp1):
            temp8.append("Name;Date;Name_Parent;Amount_Est;Repeats_X_More_Times\n")
            break
        temp2 = read_nth(fname,temp1)
        temp8.append(temp2.strip()+";"+str(temp3.count(temp2.split(";")[0]))+"\n")
        temp3.append(temp2.split(";")[0])
    f = open(fname, "w")
    for temp9 in reversed(temp8):
        f.write(temp9)
    f.close()
path = r'C:\Users\USERname4\Desktop'
all = glob.glob(path + r"\*.csv")
l = []
for f in all:
    f2 = f[:-3]+"txt"
    copyfile(f, f2)
    showRepetitions(f2)
    df1 = pd.read_csv(f2, sep =";", index_col = None, header = 0)
    os.remove(f2)
    l.append(df1)
df = pd.concat(l, axis = 0)
print(df)

【讨论】:

不知何故,csv 文件的串联不再起作用。对于df = pd.concat(l, axis = 0),我收到错误消息“ValueError:没有要连接的对象”。当然我已经调整了文件路径。你知道可能是什么原因吗? 它对我有用 100% 哈哈。也许是文件路径斜线方向。我使用 Windows,所以我的文件路径斜线方向与你的文件路径斜线方向不同。有 2 行需要更改斜线方向。确保同时更改它们。 啊,我的错,谢谢指出。 :) 我没有更改 glob.glob 行中的斜线。不幸的是,我不得不在 1.5 小时后停止执行代码,因为我的 df 大小为 350,000x30。是否有另一种更快的方法来实现所需的输出? @mcm 啊,你需要效率,我明白了。唉,我专门研究低效的编码。哈哈。但严肃地说,我认为使用这种预处理方法不会很有效。但是,我假设如果您在 pandas 本身中随时处理它,您可以获得更好的效率。在进行中的处理将比预处理占用更少的资源。但是,我对熊猫并不精通 :( 没关系!无论如何,非常感谢您的帮助!【参考方案2】:

解决了这个问题。也许这会对将来的某人有所帮助:

在一个新的 df df_max 中,我从 df 中提取了所有具有最近日期的名称,因为在相应的最近日期之后没有进一步的条目 (dummy = 0) 。然后,我只保留了df_max 中将用于合并的相关列。接下来,在新列Rep 中,我将每个值设置为0。在将dfdf_max 两个dfs 合并到df_newNameDate 上后,所有最近的条目,无论NameDate 组合出现的频率如何,都用@ 填充987654334@Rep。最后,我用1 填充了Repnan

df = df.sort_values(by=["Name", "Date"])

df_max = pd.DataFrame(df.sort_values("Date").groupby("Name").last().reset_index())
df_max = df_max[["Name", "Date"]]
df_max["Rep"] = "0"

df_new = pd.merge(df, df_max, how="left", left_on=["Name", "Date"], right_on = ["Name", "Date"])
df_startups_new = df_startups_new.fillna(1)

【讨论】:

以上是关于如果以后在 python (pandas) 中出现相同的值,则为虚拟的主要内容,如果未能解决你的问题,请参考以下文章

python 3、pandas 和创建新列失败并出现 keyerror

Python pandas:如果A列值出现不止一次,则分配B列的第一个值

pandas哪个版本好

Python数据分析库pandas ------ pandas

在 python pandas 中使用 groupby 的列中出现的百分比

python pandas怎么跳读sheet?