Сравните и найдите повторяющиеся значения (не целые столбцы) во фрейме данных с помощью python

У меня есть большой массив данных расписаний, и мне нужно подсчитать количество проведенных экспериментов. Проблема в том, что использование for повторяется в строках (что нормально), но дублируется в некоторых, но не во всех столбцах. Я хочу удалить вторую запись (если она дублируется), но я не могу удалить весь второй столбец, потому что он также будет содержать некоторые новые значения. Как я могу сравнить отдельные записи для двух столбцов бок о бок и удалить вторую, если есть дубликат? Продолжительность для этого составляет максимум два дня, поэтому три дня подряд новое событие с тем же названием, начиная с третьего дня. Фактический текст для названий экспериментов сложен, а фрейм данных имеет ширину 120 столбцов, поэтому ввод его в виде списка или словаря невозможен. Я надеюсь на функцию python или numpy, но мог бы использовать цикл.

Вот изображения для примера начального фрейма данных и желаемого вывода. пример начального фрейма данных

пример дедуплицированного фрейма данных

введите здесь описание изображения

введите здесь описание изображения


person Jordan    schedule 15.09.2020    source источник
comment
посмотрите на аргумент subset в drop_duplicates   -  person dubbbdan    schedule 16.09.2020
comment
pandas.DataFrame.drop_duplicates интересен, но для фрейма данных такого размера каждая строка будет уникальной. Кроме того, я хочу удалять не строки, а отдельные значения в столбцах. Для меня каждый ряд — это отдельный элемент оборудования, дубликаты которого используются несколько дней подряд для одного и того же теста. Чтобы подсчитать количество тестов, мне нужны дедуплицированные дни (столбцы), а не строки (отдельные единицы оборудования).   -  person Jordan    schedule 16.09.2020


Ответы (2)


df = pd.DataFrame({
    'Monday':['exp_A','exp_A','exp_A','exp_A','exp_B',np.nan,np.nan,np.nan,'exp_D','exp_D'],
    'Tuesday':['exp_A','exp_A','exp_A','exp_A','exp_B','exp_B','exp_C','exp_C','exp_D','exp_D'],
    'Wednesday':['exp_A','exp_D',np.nan,np.nan,np.nan,'exp_B','exp_C','exp_C','exp_C',np.nan],
    'Thursday':['exp_A','exp_D',np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,'exp_C',np.nan]
    })

Сравните каждый столбец со следующим столбцом:

for col in range(df.shape[1] - 1):

    duplicate = df.iloc[:,col] == df.iloc[:,col+1]  #check corresponding value in next column 
    df.loc[duplicate, df.columns[col+1] ] = np.nan  #set new value or NA 

Примечание. Вы можете использовать любой тип значения NA вместо np.nan, если вы используете объект dtype в своих данных. Но если вы хотите повысить производительность, сопоставьте название эксперимента с числовыми значениями и используйте np.nan в качестве значения NA.

person Param Patidar    schedule 16.09.2020

Это хак и похож на ответ @Params, но будет быстрее, потому что вы не звоните .iloc много. Основная идея состоит в том, чтобы транспонировать фрейм данных и повторить операцию столько раз, сколько вам нужно для сравнения всех столбцов. Затем перенесите его обратно, чтобы получить результат в OP.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'Monday':['exp_A','exp_A','exp_A','exp_A','exp_B',np.nan,np.nan,np.nan,'exp_D','exp_D'],
    'Tuesday':['exp_A','exp_A','exp_A','exp_A','exp_B','exp_B','exp_C','exp_C','exp_D','exp_D'],
    'Wednesday':['exp_A','exp_D',np.nan,np.nan,np.nan,'exp_B','exp_C','exp_C','exp_C',np.nan],
    'Thursday':['exp_A','exp_D',np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,'exp_C',np.nan]
    })


df = df.T

for i in range(int(np.ceil(df.shape[0]/2))):

    df[(df == df.shift(1))& (df != df.shift(2))] = np.nan
    
df = df.T

  Monday Tuesday Wednesday Thursday
0  exp_A     NaN     exp_A      NaN
1  exp_A     NaN     exp_D      NaN
2  exp_A     NaN       NaN      NaN
3  exp_A     NaN       NaN      NaN
4  exp_B     NaN       NaN      NaN
5    NaN   exp_B       NaN      NaN
6    NaN   exp_C       NaN      NaN
7    NaN   exp_C       NaN      NaN
8  exp_D     NaN     exp_C      NaN
9  exp_D     NaN       NaN      NaN
person dubbbdan    schedule 16.09.2020