如果以后在 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
中创建一个虚拟变量,指示相同名称是否在以后再次出现。
我想过循环遍历Name
和Date
这两列,这样对于每个具有最年轻日期的名称都设置一个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
。在将df
和df_max
两个dfs 合并到df_new
列Name
和Date
上后,所有最近的条目,无论Name
和Date
组合出现的频率如何,都用@ 填充987654334@Rep
。最后,我用1
填充了Rep
的nan
。
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列的第一个值
Python数据分析库pandas ------ pandas