簡體   English   中英

Pandas 減去上面的行

[英]Pandas substract above row

基本上這是我面臨的挑戰

具有時間范圍和唯一 ID 的數據集,我需要做的是查找 ID 在日期范圍內是否重復。

123 transaction 1/1/2021
345 transaction 1/1/2021
123 transaction 1/2/2021
123 transaction 1/20/2021

我想為 ID 123 返回 1,因為重復交易在 7 天的范圍內。

我可以使用 Excel 來做到這一點,並且我添加了更多的日期范圍,具體取決於日期,例如周三最多 6 天、周四 5 天、周五 4 天。 但我不知道如何用 pandas 來完成這個......

我想使用 pandas 執行此操作的原因是因為每個數據集最多有 1M 行,並且使用 Excel 需要很長時間才能完成,除此之外,我需要按類別進行拆分,而且做所有這些手動工作很痛苦.

關於如何完成這項任務有什么建議或想法嗎?

您提供的有關您的情況的上下文和數據很少,但您可能可以執行以下操作:

>>> df
     id         type       date
0  123  transaction 2021-01-01
1  345  transaction 2021-01-01
2  123  transaction 2021-01-02
3  123  transaction 2021-01-20

>>> dupes = df.groupby(pd.Grouper(key='date', freq='W'))['id'].apply(pd.Series.duplicated)
>>> dupes
0    False
1    False
2     True
3    False
Name: id, dtype: bool

在那里,第2項(第三項)為True ,因為過去一周已經發生了123次。

據我了解這個問題,我認為這就是你所需要的。

from datetime import datetime
import pandas as pd

df = pd.DataFrame({
    "id": [123, 345, 123, 123],
    "name": ["transaction", "transaction", "transaction", "transaction"],
    "date": ["01/01/2021", "01/01/2021", "01/02/2021", "01/10/2021"]
})

def dates_in_range(dates):
    num_days_frame = 6
    processed_dates = sorted([datetime.strptime(date, "%m/%d/%Y") for date in dates])
    difference_in_range = any(abs(processed_dates[i] - processed_dates[i-1]).days < num_days_frame  for i in range(1, len(processed_dates)))
    return difference_in_range and 1 or 0

group = df.groupby("id")
df_new = group.apply(lambda x: dates_in_range(x["date"]))

print(df_new)
"""
print(df_new)
id
123    1
345    0
"""

在這里,您首先按id分組,以便在同一行中獲得該特定 id 的所有日期。

之后,對聚合日期應用逐行 function 操作,以便首先對它們進行排序,然后檢查連續項目之間的差異是否大於定義的范圍。 如果日期接近,排序確保連續差異實際上會導致正確或錯誤的結果。

最后,如果存在任何連續排序日期的差小於num_days_frame (6) 的此類行,則返回 1,否則返回 0。

話雖如此,這可能不如對每一行進行排序那樣高效。 避免這種情況的一種方法是首先對整個df進行排序並應用組操作以確保排序日期。

自由度:

df = pd.read_csv(StringIO(
    """id,trans_date
    123,1/1/2021
    345,1/1/2021
    123,1/2/2021
    123,1/20/2021
    345,1/3/2021
    """
)) # added extra record for demo
df
    id  trans_date
0   123 1/1/2021
1   345 1/1/2021
2   123 1/2/2021
3   123 1/20/2021
4   345 1/3/2021

df['trans_date'] = pd.to_datetime(df['trans_date'])

由於您必須分別查看每個 id,您可以按 id 分組,然后獲取最大和最小日期,如果差值大於 7,則為 1。否則為 0。

result = df.groupby('id')['trans_date'].apply(
    lambda x: True if (x.max()-x.min()).days > 7 else False)
result
id
123     True
345    False
Name: trans_date, dtype: bool

如果您只需要所需的 ID,那么

result.index[result].values
array([123])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM