比较行值和整个数据帧

时间:2019-07-26 17:02:58

标签: python pandas

我需要知道一个数据框中有多少行与每一行的某些条件匹配。

例如,对于每一行,我需要计算有多少行具有相同类型,并且开始时间小于该行的开始时间,并且结束时间大于该行的结束时间。

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)

但这需要花费很长时间,我想对一个指数级更大的数据框进行相同的分析。

3 个答案:

答案 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()