Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 根据另一列中的日期和标志筛选出行_Python_Pandas_Dataframe_Group By_Pandas Groupby - Fatal编程技术网

Python 根据另一列中的日期和标志筛选出行

Python 根据另一列中的日期和标志筛选出行,python,pandas,dataframe,group-by,pandas-groupby,Python,Pandas,Dataframe,Group By,Pandas Groupby,使用python数据帧df: Customer | date_transaction_id | first_flag | dollars ABC 2015-10-11-123 Y 100 BCD 2015-03-05-872 N 150 BCD 2015-01-01-923 N -300 ABC 2015-04

使用python数据帧
df

Customer | date_transaction_id    | first_flag | dollars
ABC        2015-10-11-123              Y         100
BCD        2015-03-05-872              N         150
BCD        2015-01-01-923              N         -300
ABC        2015-04-04-910              N         -100
ABC        2015-12-12-765              N         -100
上述客户ABC在4月份归还了房产,然后在11月份购买了一些东西。在我的分析中,我需要开始将他们的第一笔积极交易计算为他们与公司的第一笔交易。如何排除客户ABC的第一笔交易?请注意,客户机BCD不是新客户机,因此不应排除任何行

那么,如何排除日期早于
first\u标志的交易

首先,我获取过期的日期\u事务\u id并将其格式化为日期字段

df['date'] = df['date_transaction_id'].astype(str).str[:10]
df['date']= pd.to_datetime(df['date'], format='%Y-%m-%d')
然后我会按客户和日期分类

df = df.sort_values(['Customer', 'date'], ascending=[True, False])
但是现在我陷入了困境,如何按客户机删除日期在
第一个\u标志
之前的行。请注意,在标记为Y的事务之前,客户机可以有一个、一个或多个事务

这是我正在寻找的输出:

Customer | date       | first_flag | dollars
ABC        2015-10-11      Y         100
ABC        2015-12-12      N         -100
BCD        2015-01-01      N         -300
BCD        2015-03-05      N         150
Customer | date       | first_flag | dollars
ABC        2015-10-11      Y         100
ABC        2015-12-12      N         -100
BCD        2015-01-01      N         -300
BCD        2015-03-05      N         150

下面是一个对groupby对象的每组进行操作的函数

def drop_before(obj):
    # Get the date when first_flag == 'Y'
    y_date = obj[obj.first_flag == 'Y'].date
    if not y_date.values:
        # If it doesn't exist, just return the DataFrame
        return obj
    else:
        # Find where your two drop conditions are satisfied
        cond1 = obj.date < y_date[0]
        cond2 = abc.first_flag == 'N'
        to_drop = obj[cond1 & cond2].index
        return obj.drop(to_drop)

res = df.groupby('Customer').apply(drop_before)
res = res.set_index(res.index.get_level_values(1))
print(res)
  Customer date_transaction_id first_flag  dollars       date
4      ABC      2015-12-12-765          N     -100 2015-12-12
0      ABC      2015-10-11-123          Y      100 2015-10-11
1      BCD      2015-03-05-872          N      150 2015-03-05
2      BCD      2015-01-01-923          N     -300 2015-01-01
def下降前(obj):
#获取第一个_标志==“Y”时的日期
y_date=obj[obj.first_flag=='y'].date
如果不是y_date.values:
#如果它不存在,只需返回数据帧
返回obj
其他:
#找到满足两个放置条件的位置
cond1=对象日期
因此,为每组客户分别绘制数据帧(1个用于ABC,1个用于BCD)。然后,当您使用
apply
时,
drop\u before
将应用于每个子帧,然后将它们重新组合


这假设每个客户最多只有一个
first\u标志==“Y”
。您的问题似乎就是这样。

回答您的第一个问题,即排除带有标记“Y”的客户的第一笔交易:

# Convert `date_transaction_id` to date timestamp.
df = df.assign(transaction_date=pd.to_datetime(df['date_transaction_id'].str[:10]))

# Find first transaction dates by customer.
first_transactions = (
    df[df['first_flag'] == 'Y']
    .groupby(['Customer'], as_index=False)['transaction_date']
    .min())

# Merge first transaction date to dataframe.
df = df.merge(first_transactions, how='left', on='Customer', suffixes=['', '_first'])

# Filter data and select relevant columns.
>>> (df[df['transaction_date'] >= df['transaction_date_first']]
     .sort_values(['Customer', 'transaction_date'])
     [['Customer', 'transaction_date', 'first_flag', 'dollars']])
  Customer transaction_date first_flag  dollars
0      ABC       2015-10-11          Y      100
4      ABC       2015-12-12          N     -100
2      BCD       2015-01-01          N     -300
1      BCD       2015-03-05          N      150
import pandas as pd
df = pd.DataFrame([['ABC','2015-10-11','Y',100],
                  ['BCD','2015-03-05','N',150],
                  ['BCD','2015-01-01','N',-300],
                  ['ABC','2015-04-04','N',-100],
                  ['ABC','2015-12-12','N', -100]], 
                  columns=['Customer','date', 'first_flag','dollars'])

# Extract the original columns
cols = df.columns

# Create a label column of whether the customer has a 'Y' flag
df['is_new'] = df.groupby('Customer')['first_flag'].transform('max')

# Apply the desired function, ie. dropping the first transaction
# to the matching records, drop index columns in the end

new_customers = (df[df['is_new'] == 'Y']
                 .sort_values(by=['Customer','date'])
                 .groupby('Customer',as_index=False)
                 .apply(lambda x: x.iloc[1:]).reset_index()
                 [cols])

# Extract the rest
old_customers = df[df['is_new'] != 'Y']

# Concat the transformed and untouched records together
pd.concat([new_customers, old_customers])[cols]
输出:


首先将
第一个\u标志
替换为整数值

df.first_flag = df.first_flag.replace({'N' : 0, 'Y' : 1})
现在,
groupby
打开
Customer
并检查
cumsum
wrt
first\u标志的
max

df = df.groupby('Customer')[['date', 'first_flag', 'dollars']]\
                .apply(lambda x: x[x.first_flag.cumsum() == x.first_flag.max()])\
                .reset_index(level=0)
df
  Customer       date  first_flag  dollars
0      ABC 2015-10-11           1      100
4      ABC 2015-12-12           0     -100
2      BCD 2015-01-01           0     -300
1      BCD 2015-03-05           0      150
可选:使用旧的
Y
/
N
替换整数值

df.first_flag = df.first_flag.replace({0 : 'N', 1 : 'Y'})  
df

  Customer       date first_flag  dollars
0      ABC 2015-10-11          Y      100
4      ABC 2015-12-12          N     -100
2      BCD 2015-01-01          N     -300
1      BCD 2015-03-05          N      150

所有预设与c相同ᴏʟᴅsᴘᴇᴇᴅ's答案,在我的答案中,我使用了
idxmax


预设



请注意,您希望删除最早的日期,尽管您将日期列按降序排序…非常正确-感谢您的捕获!天哪,打字错误_T@Wen哈哈…:p非常感谢-有没有一种方法不必在groupby-df.groupby('Customer')[[['date','first_flag','dollars']中列出所有列名;我的原始数据集大约有30列;如果没有其他方法,我将列出代码中的全部30个;在我的示例中,我没有显示全部30个,因为这一步不需要它们,但它们对于我的聚合和KPI是必需的。@jeangelj
df.groupby(df.columns.difference(['Customer'])…
:)fyi-对于括号内的行,例如
pd.to\u datetime(df['date\u transaction\u id'),不需要换行符“\”\
谢谢-我需要删除Y标志之前的所有事务,而不仅仅是第一个事务,因此一些客户可能只有一个,而其他客户可能有很多非常感谢@Brad;我现在正在尝试此选项-我有一个相当大的数据集,它仍在运行
df.first_flag = df.first_flag.replace({0 : 'N', 1 : 'Y'})  
df

  Customer       date first_flag  dollars
0      ABC 2015-10-11          Y      100
4      ABC 2015-12-12          N     -100
2      BCD 2015-01-01          N     -300
1      BCD 2015-03-05          N      150
df['date']= pd.to_datetime(df['date_transaction_id']\
                            .astype(str).str[:10], format='%Y-%m-%d')
df=df.sort_values(['Customer','date']).replace({'N' : 0, 'Y' : 1}).reset_index(drop=True)
L=df.groupby('Customer')['first_flag'].apply(lambda x : x.index>=x.idxmax()).apply(list).values.tolist()
import functools
L=functools.reduce(lambda x,y: x+y,L)
df[L]


Out[278]: 
  Customer date_transaction_id  first_flag  dollars       date
1      ABC      2015-10-11-123           1      100 2015-10-11
2      ABC      2015-12-12-765           0     -100 2015-12-12
3      BCD      2015-01-01-923           0     -300 2015-01-01
4      BCD      2015-03-05-872           0      150 2015-03-05