2016-03-08 4 views
1

Я имею дело с очень большим кадром данных, и я использую pandas для проведения анализа. Кадр данных структурирована следующим образомКак эффективно удалить повторяющиеся строки из DataFrame

import pandas as pd 

df = pd.read_csv("data.csv") 
df.head() 

    Source Target Weight 
0  0 25846  1 
1  0 1916  1 
2 25846  0  1 
3  0 4748  1 
4  0 16856  1 

Вопрос заключается в том, что я хочу, чтобы удалить все «дубликаты». В том смысле, что если у меня уже есть строка, содержащая Source и Target, я не хочу, чтобы эта информация повторялась в другой строке. Например, строки 0 и 2 являются «дублирующими» в этом смысле, и только один из них должен быть сохранен.

Простой способ избавиться от всех «дублей» является

for index, row in df.iterrows(): 
    df = df[~((df.Source==row.Target)&(df.Target==row.Source))] 

Однако этот подход ужасно медленно, так как мой кадр данных имеет около 3 миллионов строк. Как вы думаете, есть ли лучший способ сделать это?

ответ

3

Создать две временные столбцы, чтобы сохранить minimum(df.Source, df.Target) и maximum(df.Source, df.Target), а затем проверить дублированные строки на duplicated() метод:

import numpy as np 

import pandas as pd 

df = pd.DataFrame(np.random.randint(0, 5, (20, 2)), columns=["Source", "Target"]) 

df["T1"] = np.minimum(df.Source, df.Target) 
df["T2"] = np.maximum(df.Source, df.Target) 

df[~df[["T1", "T2"]].duplicated()] 
+0

спасибо, что было абсолютно приветливым! – Brian

0

Не нужно (как обычно) использовать петлю с фреймворком данных. Используйте Series.isin метод:

Так начать с этого:

df = pandas.DataFrame({ 
    'src': [0, 0, 25, 0, 0], 
    'tgt': [25, 12, 0, 85, 363] 
}) 

print(df) 



src tgt 
0 0 25 
1 0 12 
2 25 0 
3 0 85 
4 0 363 

Затем выберите все, где src не в tgt:

df[~(df['src'].isin(df['tgt']) & df['tgt'].isin(df['src']))] 

    src tgt 
1 0 12 
3 0 85 
4 0 363 
+0

Это удалит строки, которые на самом деле не дублируются. Рассмотрим 'df = pd.DataFrame ({" src ": [1,2,3]," tgt ": [2,3,1]})'. – DSM

+0

@DSM Я не думаю, что OP означает «дублировать», как это понимают большинство пользователей панды. Учитывая ограниченный объем предоставленных данных выборки, это воспроизводит вывод из кода OP. –

+0

Да, я думаю, что получаю это, но IIUC OP хочет удалить [2,1], если он уже видел [1,2]. Пример, который я дал, не имеет никаких «дубликатов» в этом смысле, но ваш код удаляет их все. – DSM

0

Ваш источник и цели являются взаимоисключающими (т. вы можете иметь один, но не оба). Почему бы не добавить их вместе (например, 25846 + 0), чтобы получить уникальный идентификатор. Затем вы можете удалить ненужный столбец Target (сокращение памяти), а затем удалить дубликаты. Если ваши веса не совпадают, по умолчанию он будет первым.

df.Source += df.Target 
df.drop('Target', axis=1, inplace=True) 
df.drop_duplicates(inplace=True) 

>>> df 
    Source Weight 
0 25846  1 
1 1916  1 
3 4748  1 
4 16856  1 
+0

Даже если это имело смысл (скажем, Source и Target - метки позиции, а Weight - это расстояние: тогда было бы нецелесообразно добавлять Source и Target), что, если есть строки Source/Target из 0,2 и 1 , 1? [О, подождите, извините - вы предполагаете, что этого не происходит. Я все еще не думаю, что это имеет смысл в контексте OP, но вы явно исключили этот случай.] – DSM

+0

Он основан на предположении, что в строке источника/цели есть только одно значение, другое - ноль , Это верно в примере выше с 5 строками, но, очевидно, зависит от знания того, как данные были закодированы. Если предположение верно, этот метод должен быть очень эффективным. – Alexander

Смежные вопросы