我有一个大数据框(约10毫米行)。每行都有:
如果两行属于同一类别,并且开始和结束位置重叠且公差为+ -5,我只想保留其中一行。 例如
1, cat1, 10, 20
2, cat1, 12, 21
3, cat2, 10, 25
我要过滤掉1或2。
我现在正在做的不是很有效,
import pandas as pd
df = pd.read_csv('data.csv', sep='\t', header=None)
dfs = []
for seq in df.category.unique():
dfs[seq] = df[df.category == seq]
for index, row in df.iterrows():
if index in discard:
continue
df_2 = dfs[row.category]
res = df_2[(abs(df_2.start - row.start) <= params['min_distance']) & (abs(df_2.end - row.end) <= params['min_distance'])]
if len(res.index) > 1:
discard.extend(res.index.values)
rows.append(row)
df = pd.DataFrame(rows)
我还尝试了使用数据框排序版本的另一种方法。
my_index = 0
indexes = []
discard = []
count = 0
curr = 0
total_len = len(df.index)
while my_index < total_len - 1:
row = df.iloc[[my_index]]
cond = True
next_index = 1
while cond:
second_row = df.iloc[[my_index + next_index]]
c1 = (row.iloc[0].category == second_row.iloc[0].category)
c2 = (abs(second_row.iloc[0].sstart - row.iloc[0].sstart) <= params['min_distance'])
c3 = (abs(second_row.iloc[0].send - row.iloc[0].send) <= params['min_distance'])
cond = c1 and c2 and c3
if cond and (c2 amd c3):
indexes.append(my_index)
cond = True
next_index += 1
indexes.append(my_index)
my_index += next_index
indexes.append(total_len - 1)
问题是此解决方案并不完美,有时会漏掉一行,因为重叠可能在前面几行,而不是在下一行
我正在寻找有关如何以更友好的方式解决此问题的想法,如果存在的话。
答案 0 :(得分:1)
此处的方法应为:
答案 1 :(得分:0)
您要合并所有相似的或仅合并两个连续的文档吗? 如果都相似,建议您先按类别对行进行排序,然后再对其他2列进行排序,并将相似的行压缩为一行。 如果仅连续2个,则检查下一个值是否在您设置的范围内,如果是,则将其合并。在这里,您可以了解如何:
答案 2 :(得分:0)
我不相信没有循环就可以进行数字比较,但是您可以至少使这种更简洁,更高效的一部分成为可能:
dfs = []
for seq in df.category.unique():
dfs[seq] = df[df.category == seq]
请改为使用df.groupby('category').apply(drop_duplicates).droplevel(0)
,其中drop_duplicates
是包含第二个循环的函数。然后将针对每个类别分别调用该函数,其数据框仅包含已过滤的行。输出将被组合回到单个数据帧中。数据框将是一个MultiIndex,其值为“ category”作为外部级别;可以使用droplevel(0)
删除。
第二,在类别中,您可以按两个数字列中的第一列进行排序,以进一步提高速度:
def drop_duplicates(df):
df = df.sort_values("sstart")
...
这将允许您在sstart列值超出范围时立即停止内部循环,而不是将每一行与其他行进行比较。