Python 是否打印数据框列中条件保留的日期周期?
我有一个txt。文件,其外观如下所示:Python 是否打印数据框列中条件保留的日期周期?,python,pandas,dataframe,time-series,periodicity,Python,Pandas,Dataframe,Time Series,Periodicity,我有一个txt。文件,其外观如下所示: Name 1 @Name( ) Value WATER WHP Date Unit
Name 1
@Name( ) Value WATER WHP
Date Unit Unit Unit
-------------- ---------- ---------- ---------- ----------
Name 1 20081220 2900.00 0.00 3300.00
Name 1 20081221 0.00 0.00 3390.00
Name 1 20081222 2500.00 0.00 2802.00
Name 1 20081223 0.00 0.00 3022.00
Name 1 20081224 0.00 0.00 3022.00
我使用以下代码导入python:
df = pd.read_csv(r'test_prd.txt', skiprows=6, engine="python", header=None)
df.columns = ['Test']
df.drop(df.tail(1).index, inplace = True) # because of file format
df = df.Test.str.split(expand=True)
df.rename(columns ={0:'Name', 1:'Number', 2:'Date', 3:'Value', 4:'Water', 5:'WHP'}
,inplace=True)
df['Date'] = pd.to_datetime(df['Date']).dt.floor('D').dt.strftime('%Y-%m-%d')
df['Note'] = (df['Value']).apply(lambda x: 'yes' if x==0 else '')
del df['Water']
del df['WHP']
df['Name'] = df['Name'].astype(str) + ' ' + df['Number'].astype(str)
del df['Number']
使用此代码后,数据框如下所示:
Name Date Value Note
0 Name 1 2008-12-20 2900.00
1 Name 1 2008-12-21 0.00 Yes
2 Name 1 2008-12-22 2500.00
3 Name 1 2008-12-23 0.00 Yes
4 Name 1 2008-12-24 0.00 Yes
... ... ... ... ...
78 Name 2009-03-15 0.00 Yes
79 Name 2009-03-16 3000.00
80 Name 2009-03-17 0.00 Yes
... ... ... ... ...
我想打印'Value'列等于零的时间段开始日期-结束日期,即'Note'=Yes。如果值不为零,则可以从数据帧中删除任何其他行。如果在非零值之前和之后有独立的零值,则开始日期和结束日期将相同
预期输出应如下所示:
Name Start Date End Date Value Note
1 Name 2008-12-21 2008-12-21 0.00 Yes
2 Name 2008-12-23 2009-03-15 0.00 Yes
3 Name 2009-03-17 *** 0.00 Yes
... ... ... ... ...
我试图使用条件if语句或df.loc,但我对Python的了解还不足以将其组合起来。任何建议都将不胜感激。要选择“备注”列为“是”的帧的所有行,请使用:
df.loc[df['Note'] == 'Yes']
这将生成一个只包含满足上述条件的行的帧
有关更有用的操作,请参见:
首先,让我们使用read\u csv导入您的数据帧 确保使用正确的柱分隔符替换sep值。这里我假设分隔符是一个或多个空格,如果不是,请调整它。 还要确保使用parse_dates参数将Date列转换为datetime,并且该值列的类型为float 现在,由于df是您的数据帧,这个代码段应该做您想要做的事情
df["Start"] = (df["Value"] == 0) & (df["Value"].shift(1) != 0)
ddf = df[df["Value"] == 0]
ddf["Group"] = ddf["Start"].cumsum()
rdf = ddf.groupby("Group").apply(lambda x: PD.Series({"Name":x["Name"].iloc[0],
"Start Date":x["Date"].min(),
"End Date":x["Date"].max(),
"Value": 0.,
"Note": "Yes",
})).reset_index(drop=True)
这里的要点是使用一些函数以有效的方式实现您想要的。不要使用循环,如果您的数据帧很大,那么您将需要大量时间来执行代码
在这里,我首先创建一个开始列,在其中检查哪一行是零间隔系列行的开始。我将值行向前移动1个位置,然后比较每一行。“开始”列对于应该开始间隔的每一行都有一个真值。
然后删除非零值行。
然后我使用cumsum对Start列求和。这将创建一个新列,我可以使用它将应该连接的间隔分组在一起。
最后,我可以使用groupby和apply将这些组连接在一起,并为每个组创建一行新的数据框,在其中我可以从date列中获取最早和最晚的日期。
对于已发布的行,最终结果是:
Name Start Date End Date Value Note
0 Name 2008-12-21 2008-12-21 0.0 Yes
1 Name 2008-12-23 2009-03-15 0.0 Yes
2 Name 2009-03-17 2009-03-17 0.0 Yes
注释栏“是/否”是什么意思?看起来是的,只是标记了0值rows@Valentino,是的,它只是一个记号笔。数据是从另一个软件下载的,它是这样来的!谢谢你的建议!但不幸的是,这并不能解决我的问题。我需要出现这种情况的时间段,即“是”出现的第一个和最后一个日期。你好@Valentino,谢谢你的反馈。我尝试了您的示例代码,但得到的是空数据帧?输出返回的数据帧与原始数据帧大小相同,没有列。@knorr976奇怪的是,我测试了我的代码,它适合我。rdf是我发布的数据帧。您是如何在python/pandas中导入数据的?非常奇怪。我使用带有txt的pd.read_csv导入。文件然后我使用str.split拆分列。@knorr976我还使用read_csv。我已经编辑了我的答案,解释了如何导入数据帧。你能再试一次吗?还是不走运。我删除了最初在数据帧中的一些列,但最后这些列是不必要的。我在这个过程中使用del df[]。这会有影响吗?
Name Start Date End Date Value Note
0 Name 2008-12-21 2008-12-21 0.0 Yes
1 Name 2008-12-23 2009-03-15 0.0 Yes
2 Name 2009-03-17 2009-03-17 0.0 Yes