我需要知道一个数据框中有多少行与每一行的某些条件匹配。
例如,对于每一行,我需要计算有多少行具有相同类型,并且开始时间小于该行的开始时间,并且结束时间大于该行的结束时间。
index type start end
0 A 5 10
1 B 3 7
2 A 10 15
3 A 3 14
在这种情况下,对于第0行,计数应为1,因为第3行是同一类型,它从3开始,低于3结束于14,结束于10,高于10。
输出应为:
index type start end count
0 A 5 10 1
1 B 3 7 0
2 A 10 15 0
3 A 3 14 0
我通过使用lambda来做到这一点:
df['counts'] = df.apply(lambda x: len((df['type']==x[0]) & (df['start']<x[1]) & (df['end']>x[2])]), axis=1)
但这需要花费很长时间,我想对一个指数级更大的数据框进行相同的分析。
答案 0 :(得分:2)
np.(less|greater|equal).outer
当心内存复杂性
u = df[['type', 'start', 'end']].to_records()
m1 = np.less.outer(u['start'], u['start'])
m2 = np.greater.outer(u['end'], u['end'])
m3 = np.equal.outer(u['type'], u['type'])
(m1 & m2 & m3).sum(0)
array([1, 0, 0, 0])
答案 1 :(得分:2)
您可以先使用groupby()
,以便仅在“类型”内进行比较,这会减少搜索空间以及额外的布尔比较(即(df ['type'] == x [0]))
import pandas
df = pandas.DataFrame({'type':['A','B','A','A'], 'start':[5,3,10,3], 'end':[10,7,15,14]})
def get_count(df_type):
return df_type.apply(lambda x:sum((x['start']>df_type['start'])&(x['end']<df_type['end'])), axis=1)
df['count'] = df.groupby('type').apply(get_count).reset_index(drop=True)
答案 2 :(得分:0)
您的原始版本不适用于我,但这确实可行:
df['counts'] = df.apply(lambda x: ((df['type']==x["type"]) & (df['start']<x["start"]) & (df['end']>x["end"])).sum(), axis=1)
我认为user3483203的答案很好,但是如上所述,在内存方面可能是个问题。这是另一种方法,应该比您拥有的方法快一点:
df = pd.DataFrame({'type':['A','B','A','A'], 'start':[5,3,10,3], 'end':[10,7,15,14]})
df["counts"] = 0
for rows in df.iterrows():
row = rows[1]
match = df['type']==row["type"]
temp = df[match]
less = temp['start']<row["start"]
temp = temp[less]
final = temp['end']>row["end"]
df.at[rows[0], "counts"] = final.sum()