具有列值条件的 id 的最早和最新记录
Earliest and latest record for an id with a condition on a column value
我有一个 json 数据必须转换成列,我能够成功地做到这一点,它使我得到如下结果:
id
phone
country
country_code
status
timestamp
abc
123
India
91
open
2021-09-01
abc
123
India
91
closed
2021-09-02
xyz
456
India
91
open
2021-09-01
xyz
456
India
91
closed
2021-09-02
xyz
456
India
91
open
2021-09-03
ijk
789
India
91
open
2021-09-01
ijk
789
India
91
closed
2021-09-02
ijk
789
India
91
open
2021-09-03
ijk
789
India
91
closed
2021-09-04
suv
000
US
1
Open
2021-09-05
这是一个状态数据,表示某个任务的 activity 何时打开或关闭。已关闭的 activity 也可以重新打开,也可以重新关闭或保持打开状态。但状态键的值仅为 open/closed。
现在,我需要的是最早打开的时间戳和最晚关闭的时间戳。这会告诉我他们什么时候第一次打开 activity 以及它最后一次关闭是什么时候。
结果应该是这样的:
id
phone
country
country_code
status
timestamp
abc
123
India
91
open
2021-09-01
abc
123
India
91
closed
2021-09-02
xyz
456
India
91
open
2021-09-01
xyz
456
India
91
closed
2021-09-02
ijk
789
India
91
open
2021-09-01
ijk
789
India
91
closed
2021-09-04
suv
000
US
1
Open
2021-09-05
status = open 只能跟随 status = closed。它不能在没有关闭的情况下重新打开,但它可以保持打开状态并且永远不会关闭。
对于 id=abc 有一个 open 和 closed 状态,所以我需要这两个;对于 id = xyz 有一个重新打开,但我不在乎并且仍然需要最早打开和唯一关闭的。对于 id = ijk,有一个重新打开和一个重新关闭,所以我需要最早打开和最晚关闭。对于 id = suv 从来没有关闭,所以它应该 return 只打开记录。 (这里只有 id 是唯一的,不能为 null。即使 phone 看起来也很独特,但它也可以为 null)
所以,基本上任何 ID 最多只能有 2 条记录(如果从来没有关联的关闭状态,则为 1 条)。任何 i 的第一条记录是 status = open 和最早的时间戳。但是,当状态关闭并且它有多个关闭时,那么该特定 id 的最后一个关闭。
我必须将数据放入模式中,我可以使用 rank 子句轻松完成此操作,但这在 pandas 中可行吗?
可以groupby,过滤,然后取first/last如下:
# copy, clean df
# df = pd.read_clipboard("\s\s+")
# df["status"] = df.status.str.lower()
# df["timestamp"] = pd.to_datetime(df.timestamp)
# df = df.sort_values("timestamp")
# this stores the original index as a column, creates a new
df = df.reset_index()
df_open = df[df.status == "open"].groupby(["id"], as_index=False).first()
df_closed = df[df.status == "closed"].groupby(["id"], as_index=False).last()
# discard the temp index, set back to original index
sol = pd.concat([df_open, df_closed]).set_index("index", drop=True).sort_index()
输出:
id phone country country_code status timestamp
index
0 abc 123 India 91 open 2021-09-01
1 abc 123 India 91 closed 2021-09-02
2 xyz 456 India 91 open 2021-09-01
3 xyz 456 India 91 closed 2021-09-02
5 ijk 789 India 91 open 2021-09-01
8 ijk 789 India 91 closed 2021-09-04
9 suv 0 US 1 open 2021-09-05
我有一个 json 数据必须转换成列,我能够成功地做到这一点,它使我得到如下结果:
id | phone | country | country_code | status | timestamp |
---|---|---|---|---|---|
abc | 123 | India | 91 | open | 2021-09-01 |
abc | 123 | India | 91 | closed | 2021-09-02 |
xyz | 456 | India | 91 | open | 2021-09-01 |
xyz | 456 | India | 91 | closed | 2021-09-02 |
xyz | 456 | India | 91 | open | 2021-09-03 |
ijk | 789 | India | 91 | open | 2021-09-01 |
ijk | 789 | India | 91 | closed | 2021-09-02 |
ijk | 789 | India | 91 | open | 2021-09-03 |
ijk | 789 | India | 91 | closed | 2021-09-04 |
suv | 000 | US | 1 | Open | 2021-09-05 |
这是一个状态数据,表示某个任务的 activity 何时打开或关闭。已关闭的 activity 也可以重新打开,也可以重新关闭或保持打开状态。但状态键的值仅为 open/closed。
现在,我需要的是最早打开的时间戳和最晚关闭的时间戳。这会告诉我他们什么时候第一次打开 activity 以及它最后一次关闭是什么时候。
结果应该是这样的:
id | phone | country | country_code | status | timestamp |
---|---|---|---|---|---|
abc | 123 | India | 91 | open | 2021-09-01 |
abc | 123 | India | 91 | closed | 2021-09-02 |
xyz | 456 | India | 91 | open | 2021-09-01 |
xyz | 456 | India | 91 | closed | 2021-09-02 |
ijk | 789 | India | 91 | open | 2021-09-01 |
ijk | 789 | India | 91 | closed | 2021-09-04 |
suv | 000 | US | 1 | Open | 2021-09-05 |
status = open 只能跟随 status = closed。它不能在没有关闭的情况下重新打开,但它可以保持打开状态并且永远不会关闭。
对于 id=abc 有一个 open 和 closed 状态,所以我需要这两个;对于 id = xyz 有一个重新打开,但我不在乎并且仍然需要最早打开和唯一关闭的。对于 id = ijk,有一个重新打开和一个重新关闭,所以我需要最早打开和最晚关闭。对于 id = suv 从来没有关闭,所以它应该 return 只打开记录。 (这里只有 id 是唯一的,不能为 null。即使 phone 看起来也很独特,但它也可以为 null)
所以,基本上任何 ID 最多只能有 2 条记录(如果从来没有关联的关闭状态,则为 1 条)。任何 i 的第一条记录是 status = open 和最早的时间戳。但是,当状态关闭并且它有多个关闭时,那么该特定 id 的最后一个关闭。
我必须将数据放入模式中,我可以使用 rank 子句轻松完成此操作,但这在 pandas 中可行吗?
可以groupby,过滤,然后取first/last如下:
# copy, clean df
# df = pd.read_clipboard("\s\s+")
# df["status"] = df.status.str.lower()
# df["timestamp"] = pd.to_datetime(df.timestamp)
# df = df.sort_values("timestamp")
# this stores the original index as a column, creates a new
df = df.reset_index()
df_open = df[df.status == "open"].groupby(["id"], as_index=False).first()
df_closed = df[df.status == "closed"].groupby(["id"], as_index=False).last()
# discard the temp index, set back to original index
sol = pd.concat([df_open, df_closed]).set_index("index", drop=True).sort_index()
输出:
id phone country country_code status timestamp
index
0 abc 123 India 91 open 2021-09-01
1 abc 123 India 91 closed 2021-09-02
2 xyz 456 India 91 open 2021-09-01
3 xyz 456 India 91 closed 2021-09-02
5 ijk 789 India 91 open 2021-09-01
8 ijk 789 India 91 closed 2021-09-04
9 suv 0 US 1 open 2021-09-05