【问题标题】:build a new column based on previous row values根据前一行值构建一个新列
【发布时间】:2021-07-28 16:24:03
【问题描述】:

我有一个数据框,下面给出了它的 sn-p。

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)

谢谢。

【问题讨论】:

  • 请分享您的尝试。
  • @RJAdriaansen 我已经更新了我的工作。
  • 您确实在第 0 行和第 1 行中重复了 ID 和日期吗?
  • @HenryYik 是的。这就是我现在遇到的问题。其他一切都适用于最后给出的代码。

标签: python-3.x pandas dataframe data-analysis data-preprocessing


【解决方案1】:

一种方法是groupby,通过ID找到与缺失日期的集合差异,构造一个新的df,concat与原始的,最后rankStudyDate

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

【讨论】:

  • '学习日期';您的代码中缺少列。请务必看一看。
  • @Shiva 添加在上面。
  • 非常感谢。这工作得很好。
【解决方案2】:

使用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

【讨论】:

  • 非常感谢!这给了我新的想法。
猜你喜欢
  • 2019-11-10
  • 1970-01-01
  • 1970-01-01
  • 2019-04-16
  • 2016-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-21
相关资源
最近更新 更多