我有一个数据框,df_A有两列'amin'和'amax',这是一组时间范围。
我的目标是找出df_B中的列是否位于df_A'amin'和'amax'列中任何范围行之间。
df_A[['amin','amax'] ]
amin amax
0 2016-07-16 19:37:03 2016-07-17 11:16:32
1 2016-07-04 21:15:54 2016-07-05 10:57:46
2 2016-07-24 23:30:41 2016-07-25 15:38:02
3 2016-07-12 03:02:38 2016-07-12 22:11:01
df_B['created_date']
created_date
2016-07-17 01:16:32
2016-07-05 10:15:54
2016-07-12 12:11:01
df_A['amin'] = pd.to_datetime(df_A['amin'], errors='coerce')
df_A['amax'] = pd.to_datetime(df_A['amax'], errors='coerce')
df_B['created_date'] = pd.to_datetime(df_B['created_date'],errors='coerce')
def dt2epoch(value):
epoch = (value - pd.to_datetime(datetime(2015,12,31).strftime('%Y-%m-%d %H:%M:%S.%f'))).total_seconds()
return epoch
df_A['amax_epoch']=df_A['amax'].apply(dt2epoch)
df_A['amin_epoch']=df_A['amin'].apply(dt2epoch)
df_B['created_date_epoch']=df_B['created_date'].apply(dt2epoch)
def make_tuple(row):
n= len(row)
row = [(x,row[n - 1]) for x in row]
return row
minMaxTuple = minMax.apply(make_tuple, axis =1)
以上是我的代码的一部分,我在下面尝试过(不确定是否有必要):
但是,df_A和df_B具有不同的行数。另外,我没有任何id列将它们合并在一起。
label = []
for l in df_B['created_date_epoch']:
if (m[0] for m in minMaxTuple) <= l <= (m[1] for m in minMaxTuple):
label.append('1')
else:
label.append('0')
然而,当我运行这个时,我得到的'label'结果是一个空列表。
此外,标签应该是与df_A具有相同行数的列。
最后,我想在df_A中添加一个新的“标签”列:
minMaxTuple label
(2016-07-16 19:37:03, 2016-07-17 11:16:32) 1
(2016-07-04 21:15:54, 2016-07-05 10:57:46) 1
(2016-07-24 23:30:41, 2016-07-25 15:38:02) 0
(2016-07-12 03:02:38, 2016-07-12 22:11:01) 1
答案 0 :(得分:0)
一种解决方案是查看df_b中的created_date
是否落在amin
和amax
之间是否使用布尔逻辑。在df_a
中每行的行计算中,您可以使用以下逻辑:
if sum((row['amin'] > df_b['created_date']) | (row['amax'] < df_b['created_date'])) == len(df_b)
在本章中,我使用逻辑运算符|
检查amin
是否小于created_date
或amax
是否小于created_date
。如果语句为True
,您可以断定创建日期不在amin
和amax
创建的时间段之间。如果created_dates
在amin
和amax
创建的时段之间没有任何一个,则可以将0
的值分配给df_a['label']
:类似于:< / p>
import pandas as pd
from StringIO import StringIO
def myfunc(row, df_b):
if sum((row['amin'] > df_b['created_date']) | (row['amax'] < df_b['created_date'])) == len(df_b):
return 0
else:
return 1
a_str= """
amin,amax
2016-07-16 19:37:03,2016-07-17 11:16:32
2016-07-04 21:15:54,2016-07-05 10:57:46
2016-07-24 23:30:41,2016-07-25 15:38:02
2016-07-12 03:02:38,2016-07-12 22:11:01"""
b_str = """
created_date
2016-07-17 01:16:32
2016-07-05 10:15:54
2016-07-12 12:11:01"""
df_a = pd.read_csv(StringIO(a_str), sep=',')
df_b = pd.read_csv(StringIO(b_str), sep=',')
#Convert to datetime
df_a['amin'] = pd.to_datetime(df_a['amin'])
df_a['amax'] = pd.to_datetime(df_a['amax'])
df_b['created_date'] = pd.to_datetime(df_b['created_date'])
df_a['label'] = df_a.apply(lambda x: myfunc(x,df_b), axis=1)
返回label
中的df_a
列,预期输出为:
amin amax label
0 2016-07-16 19:37:03 2016-07-17 11:16:32 1
1 2016-07-04 21:15:54 2016-07-05 10:57:46 1
2 2016-07-24 23:30:41 2016-07-25 15:38:02 0
3 2016-07-12 03:02:38 2016-07-12 22:11:01 1
答案 1 :(得分:0)
与@dubbbdan的答案非常相似,但使用any
和and
运算符可能更简单:
any_in_range = lambda row, iterable: any(
[(row[0] < x) & (x < row[1]) for x in iterable])
df_A['label'] = df_A.apply(any_in_range, iterable=df_B['created_date'], axis=1)
print df_A
打印:
amin amax label
0 2016-07-16 19:37:03 2016-07-17 11:16:32 True
1 2016-07-04 21:15:54 2016-07-05 10:57:46 True
2 2016-07-24 23:30:41 2016-07-25 15:38:02 False
3 2016-07-12 03:02:38 2016-07-12 22:11:01 True
答案 2 :(得分:0)
我从最大日期和最小日期列创建了一个元组列表,然后在此元组列表中搜索日期时间戳。
tuple_to_search = list(zip(df_A.amin,df_A.amax))
df_B['is_true']= df_B['created_date'].map(lambda k: any(filter(lambda x : x [0]<= k <=x[1],tuple_to_search ))).astype(int)