Сравните 70% строк отдельных столбцов - PullRequest
0 голосов
/ 04 февраля 2019

Я хочу сравнить конкретные столбцы всех строк, или же 70% всех строк, если они являются уникальными, извлеките это значение, иначе значение 0, в новый столбец.

Если пример кадра данных выглядит следующим образом:

A      B           C  D  E  F  G  H  I  J  K  L   
32145  Basket      2  2  2  2  2  2  2  2  2  2
43290  Red ball    1  1  0  0  1  1  1  1  1  1
32891  wht ball    4  4  4  0  4  0  4  0  4  4
45328  grn ball    1  1  1  1  1  1  2  1  1  1
34531  blk ball    6  6  6  6  0  0  0  0  6  0

Результат должен быть следующим:

  A      B         C  D  E  F  G  H  I  J  K  L  M    
32145  Basket      2  2  2  2  2  2  2  2  2  2  2 (100% of rows are similar)
43290  Red ball    1  1  0  0  1  1  1  1  1  1  1 (80% of rows are similar)
32891  wht ball    4  4  4  0  4  0  4  0  4  4  4 (70% of rows are similar)
45328  grn ball    1  1  1  1  1  1  2  1  1  1  1 (90% of rows are similar)
34531  blk ball    6  6  6  6  0  0  0  0  6  0  0 (only 50% of rows are similar) 

Я использовал приведенный ниже ответ для нахождения 100% похожих строк.
сравнить несколько конкретныхстолбцы всех строк
Я хотел бы найти, если, по крайней мере, 70% всех строк одинаковы в противном случае 0.
Рассмотрение количества строк может изменяться, поскольку оно не постоянно все время.

Я хочу, чтобы уникальные значения (только если и более 70% строк были похожими) в результирующей строке, иначе 0. (из приведенного выше примера столбца 'M')

Приятно знать некоторыепредложения.

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Попробуйте,

n= float(len(df.iloc[:, 2:].columns.values))
df['ratio']=df.iloc[:, 2:].apply(lambda x: collections.Counter(x.values).most_common(1)[0][1]/n,axis=1)

Вывод:

       A         B  C  D  E  F  G  H  I  J  I.1  K  ratio
0  32145    Basket  2  2  2  2  2  2  2  2    2  2    1.0
1  43290  Red ball  1  1  0  0  1  1  1  1    1  1    0.8
2  32891  wht ball  4  4  4  0  4  0  4  0    4  4    0.7
3  45328  grn ball  1  1  1  1  1  1  2  1    1  1    0.9
4  34531  blk ball  6  6  6  6  0  0  0  0    6  0    0.5

Метрики производительности:

df=(pd.concat([df]*10000,ignore_index=True))

Мое предлагаемое решение:

start = time.time()
n= float(len(df.iloc[:, 2:].columns.values))
df['ratio']=df.iloc[:, 2:].apply(lambda x: collections.Counter(x.values).most_common(1)[0][1]/n,axis=1)
end = time.time()
print(end - start)

O/P: 0.7386555671691895
* 1012Решение * @ jpp:
start = time.time()
arr = df.iloc[:, 2:]
modes = stats.mode(arr.mask(arr.eq(0)), 1)[0].ravel()
df['ratio'] = arr.eq(modes, axis=0).mean(1)
end = time.time()
print(end - start)

O/P: 1.281557559967041

@ Решение Сандипа Кадапы:

start = time.time()
d = (df.iloc[:, 2:].apply(pd.value_counts, 1).drop(0, 1).max(1)/df.iloc[:, 2:].shape[1])
df['L'] = np.where(d>0.5, df.iloc[:, 2:].max(1), 0)
end = time.time()
print(end - start)

O/P: 73.34089946746826
0 голосов
/ 04 февраля 2019

Вы можете рассчитать режим по строке с помощью scipy.stats.mode, а затем взять средства.В этом примере явно игнорируются значения 0 через pd.Series.mask.Если исключить эту маску (в соответствии с приведенным ниже сравнительным тестом), если это разрешено, вы увидите улучшение производительности.

from scipy import stats

arr = df.iloc[:, 2:]
modes = stats.mode(arr.mask(arr.eq(0)), 1)[0].ravel()
df['ratio'] = arr.eq(modes, axis=0).mean(1)

print(df)

       A         B  C  D  E  F  G  H  I  J  K  L  ratio
0  32145    Basket  2  2  2  2  2  2  2  2  2  2    1.0
1  43290  Red ball  1  1  0  0  1  1  1  1  1  1    0.8
2  32891  wht ball  4  4  4  0  4  0  4  0  4  4    0.7
3  45328  grn ball  1  1  1  1  1  1  2  1  1  1    0.9
4  34531  blk ball  6  6  6  6  0  0  0  0  6  0    0.5

Сравнение производительности

Для большого числа строк и столбцов и использованияалгоритм for-like, scipy.stats.mode превосходит collections.Counter:

from scipy.stats import mode
from collections import Counter

def counter_ratio(df):
    n= float(len(df.iloc[:, 2:].columns.values))
    df['ratio']=df.iloc[:, 2:].apply(lambda x: Counter(x.values).most_common(1)[0][1]/n,axis=1)
    return df

def mode_ratio(df):
    arr = df.iloc[:, 2:].values
    df['ratio'] = np.mean(arr == mode(arr, 1)[0], axis=1)
    return df

n = 10**4
df = pd.concat([df]*n, ignore_index=True)

%timeit counter_ratio(df.copy())  # 1.88 s per loop
%timeit mode_ratio(df.copy())     # 32.7 ms per loop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...