根据前一行值构建一个新列
build a new column based on previous row values
我有一个数据框,下面给出了它的一个片段。
data = {'ID':['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C'],
'Date':['03/25/2021', '03/25/2021','03/27/2021', '03/29/2021', '03/10/2021','03/11/2021','03/15/2021','03/16/2021', '03/21/2021','03/25/2021']}
df = pd.DataFrame(data)
我正在寻找应如下所示的最终结果。
说明:对于每个ID,study_date从开始日期开始到最后日期结束。必须填写中间缺失的日期。如果原始数据框中缺少日期,则 'missing_date' 列的值为 1,否则为 0。研究日列是从开始到结束的天数按顺序递增的天数。
如果有多个具有相同日期的行,则必须保留这些行以及具有相同先前数据的新列,如图所示。
我尝试了一些东西,但我已经坚持了一段时间了。非常感谢任何帮助。
我想出了下面给出的代码。这得到 'Missing_Date' 和 'Studyday'。但是,如果有多个条目具有相同的日期,则不会显示。
def fn(x):
dr = pd.date_range(x["Date"].min(), x["Date"].max())
out = pd.DataFrame({"Date": dr}, index=range(1, len(dr) + 1))
out["Missing_Date"] = (~out["Date"].isin(x["Date"])).astype(int)
return out
# if the "Date" column is not converted:
df["Date"] = pd.to_datetime(df["Date"])
x = (
df.groupby("ID")
.apply(fn)
.reset_index()
.rename(columns={"level_1": "StudyDay"})
)
print(x)
谢谢。
一种方法是groupby
,通过ID找到与缺失日期的集合差异,构造一个新的df,concat
与原始rank
最后[=14] =]:
df["missing"] = 0
df["Date"] = pd.to_datetime(df["Date"])
new = pd.DataFrame([(k, d, 1) for k, v in df.groupby("ID")["Date"]
for d in pd.date_range(min(v), max(v))^v],
columns=df.columns)
df = pd.concat([df, new], ignore_index=True).sort_values(["ID", "Date"]).reset_index(drop=True)
print (df.assign(Studydate=df.groupby('ID')['Date'].rank(method='dense').astype(int)))
ID Date missing Studydate
0 A 2021-03-25 0 1
1 A 2021-03-25 0 1
2 A 2021-03-26 1 2
3 A 2021-03-27 0 3
4 A 2021-03-28 1 4
5 A 2021-03-29 0 5
6 B 2021-03-10 0 1
7 B 2021-03-11 0 2
8 B 2021-03-12 1 3
9 B 2021-03-13 1 4
10 B 2021-03-14 1 5
11 B 2021-03-15 0 6
12 B 2021-03-16 0 7
13 C 2021-03-21 0 1
14 C 2021-03-22 1 2
15 C 2021-03-23 1 3
16 C 2021-03-24 1 4
17 C 2021-03-25 0 5
另一种使用join(how='outer')
的方法:
data = {'ID':['A', 'A', 'A','A', 'B', 'B', 'B', 'B', 'C', 'C'],
'Date':['03/25/2021', '03/25/2021','03/27/2021', '03/29/2021', '03/10/2021','03/11/2021','03/15/2021','03/16/2021', '03/21/2021','03/25/2021']}
df = pd.DataFrame(data)
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
def reindex_by_date(df):
dates = pd.date_range(df.index.min(), df.index.max())
return df.join(pd.DataFrame(index=dates), how='outer')
df2 = (df.groupby('ID').apply(reindex_by_date).reset_index(0, drop=True)
.reset_index().rename({'index':'Date'}, axis=1))
df2['Missing Date'] = df2['ID'].isna().astype(int)
df2['ID'] = df2['ID'].fillna(method='ffill')
df2['Study Day'] = (df2['Date'] - df2.groupby('ID')['Date'].transform('min')).dt.days + 1
Date ID Missing Date Study Day
0 2021-03-25 A 0 1
1 2021-03-25 A 0 1
2 2021-03-26 A 0 2
3 2021-03-27 A 0 3
4 2021-03-28 A 0 4
5 2021-03-29 A 0 5
6 2021-03-10 B 0 1
7 2021-03-11 B 0 2
8 2021-03-12 B 0 3
9 2021-03-13 B 0 4
10 2021-03-14 B 0 5
11 2021-03-15 B 0 6
12 2021-03-16 B 0 7
13 2021-03-21 C 0 1
14 2021-03-22 C 0 2
15 2021-03-23 C 0 3
16 2021-03-24 C 0 4
17 2021-03-25 C 0 5
我有一个数据框,下面给出了它的一个片段。
data = {'ID':['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C'],
'Date':['03/25/2021', '03/25/2021','03/27/2021', '03/29/2021', '03/10/2021','03/11/2021','03/15/2021','03/16/2021', '03/21/2021','03/25/2021']}
df = pd.DataFrame(data)
我正在寻找应如下所示的最终结果。
说明:对于每个ID,study_date从开始日期开始到最后日期结束。必须填写中间缺失的日期。如果原始数据框中缺少日期,则 'missing_date' 列的值为 1,否则为 0。研究日列是从开始到结束的天数按顺序递增的天数。
如果有多个具有相同日期的行,则必须保留这些行以及具有相同先前数据的新列,如图所示。
我尝试了一些东西,但我已经坚持了一段时间了。非常感谢任何帮助。
我想出了下面给出的代码。这得到 'Missing_Date' 和 'Studyday'。但是,如果有多个条目具有相同的日期,则不会显示。
def fn(x):
dr = pd.date_range(x["Date"].min(), x["Date"].max())
out = pd.DataFrame({"Date": dr}, index=range(1, len(dr) + 1))
out["Missing_Date"] = (~out["Date"].isin(x["Date"])).astype(int)
return out
# if the "Date" column is not converted:
df["Date"] = pd.to_datetime(df["Date"])
x = (
df.groupby("ID")
.apply(fn)
.reset_index()
.rename(columns={"level_1": "StudyDay"})
)
print(x)
谢谢。
一种方法是groupby
,通过ID找到与缺失日期的集合差异,构造一个新的df,concat
与原始rank
最后[=14] =]:
df["missing"] = 0
df["Date"] = pd.to_datetime(df["Date"])
new = pd.DataFrame([(k, d, 1) for k, v in df.groupby("ID")["Date"]
for d in pd.date_range(min(v), max(v))^v],
columns=df.columns)
df = pd.concat([df, new], ignore_index=True).sort_values(["ID", "Date"]).reset_index(drop=True)
print (df.assign(Studydate=df.groupby('ID')['Date'].rank(method='dense').astype(int)))
ID Date missing Studydate
0 A 2021-03-25 0 1
1 A 2021-03-25 0 1
2 A 2021-03-26 1 2
3 A 2021-03-27 0 3
4 A 2021-03-28 1 4
5 A 2021-03-29 0 5
6 B 2021-03-10 0 1
7 B 2021-03-11 0 2
8 B 2021-03-12 1 3
9 B 2021-03-13 1 4
10 B 2021-03-14 1 5
11 B 2021-03-15 0 6
12 B 2021-03-16 0 7
13 C 2021-03-21 0 1
14 C 2021-03-22 1 2
15 C 2021-03-23 1 3
16 C 2021-03-24 1 4
17 C 2021-03-25 0 5
另一种使用join(how='outer')
的方法:
data = {'ID':['A', 'A', 'A','A', 'B', 'B', 'B', 'B', 'C', 'C'],
'Date':['03/25/2021', '03/25/2021','03/27/2021', '03/29/2021', '03/10/2021','03/11/2021','03/15/2021','03/16/2021', '03/21/2021','03/25/2021']}
df = pd.DataFrame(data)
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
def reindex_by_date(df):
dates = pd.date_range(df.index.min(), df.index.max())
return df.join(pd.DataFrame(index=dates), how='outer')
df2 = (df.groupby('ID').apply(reindex_by_date).reset_index(0, drop=True)
.reset_index().rename({'index':'Date'}, axis=1))
df2['Missing Date'] = df2['ID'].isna().astype(int)
df2['ID'] = df2['ID'].fillna(method='ffill')
df2['Study Day'] = (df2['Date'] - df2.groupby('ID')['Date'].transform('min')).dt.days + 1
Date ID Missing Date Study Day
0 2021-03-25 A 0 1
1 2021-03-25 A 0 1
2 2021-03-26 A 0 2
3 2021-03-27 A 0 3
4 2021-03-28 A 0 4
5 2021-03-29 A 0 5
6 2021-03-10 B 0 1
7 2021-03-11 B 0 2
8 2021-03-12 B 0 3
9 2021-03-13 B 0 4
10 2021-03-14 B 0 5
11 2021-03-15 B 0 6
12 2021-03-16 B 0 7
13 2021-03-21 C 0 1
14 2021-03-22 C 0 2
15 2021-03-23 C 0 3
16 2021-03-24 C 0 4
17 2021-03-25 C 0 5