Логические аргументы панд не работают (И / ИЛИ) - PullRequest
0 голосов
/ 10 октября 2019

Я строю следующий игрушечный код, чтобы проиллюстрировать мою проблему. У меня есть вес и мне нужно выбрать конкретные комбинации. Это может быть либо один вес = 1 (как в маске 1), либо применяются определенные комбинации весов (mask2). Тем не менее, маска 2 не работает как-то (по крайней мере, вторая часть). Для иллюстрации: из-за mask1 должны остаться только строки с весами 1 в определенных столбцах. Тем не менее, вывод также дает мне строки, такие как строка 1, которые не должны быть там, потому что sumABCD всегда равен 1 (см. Ниже).

import numpy as np
import pandas as pd


# random dataframe:
np.random.seed(seed=1)
df = pd.DataFrame(np.random.randint(0,5000,size=(2000, 4)), columns=list('ABCD'))
columns = list(df.columns)
for col in columns: # round up at certain threshold, to simulate weightings of 1
    other_columns = [x for x in columns if not x == col]
    df.loc[df[col] > 4700, col] = 5000
    df.loc[df[col] == 5000, other_columns] = 0

# calculate weights:
df[list(df.columns)] = df.div(df[["A", "B", "C", "D"]].sum(axis=1), axis="index")
df["sumABCD"] = df[["A", "B", "C", "D"]].sum(axis=1)

# filter
mask1 = ((df[["A", "B", "C", "D"]] == 1).any(axis=1))
for x in [0, 0.10]:
    mask2 = ((df["B"] <= x) & (df["sumABCD"] < 1.0))
    test = df[mask1 | mask2]
    print(test.head(20))

           A         B         C         D  sumABCD
1   0.287745  0.014313  0.419938  0.278004      1.0
3   0.000000  0.000000  0.000000  1.000000      1.0
8   0.000000  0.000000  1.000000  0.000000      1.0
12  1.000000  0.000000  0.000000  0.000000      1.0

1 Ответ

1 голос
/ 10 октября 2019

Редактировать :

Что касается обновленного вопроса по проблеме row 1, попробуйте выполнить команду ниже для ваших данных

df.loc[df["sumABCD"] < 1.0, "sumABCD"].map('{0:.30f}'.format)

Out[28]:
1       0.999999999999999888977697537484
13      0.999999999999999888977697537484
44      0.999999999999999888977697537484
53      0.999999999999999888977697537484
57      0.999999999999999888977697537484

Она нарезается на sumABCDстолбцы <1.0. Строка 1 на самом деле не <code>1.0. Его значения почти 1.0 и округлены до 1.0. Из-за представления чисел в компьютерной системе float не гарантирует сохранение точности в арифметических операциях. sumABCD - сумма делений в каждом столбце. Эти деления привели к потере точности, поэтому сумма возвращается только к almost 1.0

Если вам нужна дополнительная информация по float, прочитайте эту документацию https://docs.python.org/3/tutorial/floatingpoint.html


IIUC, в вашем примере кода вы думаете, что должны получить пустой фрейм данных, но это не так.

После этого

mask2 = ((df["B"] <= x) & (df["sumABCD"] < 1.0))

mask2 всегда False, поскольку (df["sumABCD"] < 1.0) всегда False

Однако, вы нарезаете df на *Оператор 1038 *, как в

test = df[mask1 | mask2]

Итак, mask2 all False не повлияет на результат. Когда mask2 - это все False, результат зависит от mask1. Такова природа оператора '|'. Следовательно, test будет зависеть от True/False из mask1. По этой причине test не является пустым кадром данных, как вы ожидаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...