Наибольшая поэлементная разница между всеми строками в кадре данных - PullRequest
0 голосов
/ 21 января 2019

Данный следующий фрейм данных:

      c1  c2  c3  c4
code
x      1   2   1   1
y      3   2   2   1
z      2   0   4   1

Для любой строки в этом фрейме данных я хочу вычислить наибольшую поэлементную абсолютную разницу между этой строкой и всеми другими строками этого фрейма данных ипоместите его в новый фрейм данных:

       x   y   z
code
x      0   2   3
y      2   0   2
z      3   2   0

(результатом, конечно же, будет треугольная матрица с главной диагональю = 0, поэтому было бы достаточно получить только верхнюю или нижнюю треугольную половину).

Так, например, максимальная поэлементная разница между строками x и y равна 2 (из столбца c1: abs(3 - 1) = 2).

Что я получил до сих пор:

df = pd.DataFrame(data={'code': ['x','y','z'], 'c1': [1, 3, 2], 'c2': [2, 2, 0], 'c3': [1,2,4], 'c4': [1,1,1]})
df.set_index('code', inplace = True)

df1 = pd.DataFrame()

for row in df.iterrows():
   df1.append((df-row[1]).abs().max(1), ignore_index = True)

При интерактивном запуске это уже выглядит близко к тому, что мне нужно, но новый df1 после этого еще пуст:

>>> for row in df.iterrows(): df1.append((df-row[1]).abs().max(1),ignore_index=True)
...
     x    y    z
0  0.0  2.0  3.0
     x    y    z
0  2.0  0.0  2.0
     x    y    z
0  3.0  2.0  0.0
>>> df1
Empty DataFrame
Columns: []
Index: []

Вопросы:

  1. Как получить результаты в новом фрейме данных df1 (с правильным индексом x, y, ...)?
  2. Это всего лишь mcve .На самом деле, df имеет около 700 строк.Не уверен, что iterrows так хорош тогда.У меня есть ощущение, что метод apply пригодится здесь, но я не могу понять это.Так есть ли какой-нибудь идиоматический / пандоподобный способ сделать это без явного перебора строк?

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Если вы хотите, чтобы ваш код выводил корректно, вы можете снова присвоить значение, вычисленное для df1.

for row in df.iterrows():
    df1 = df1.append((df-row[1]).abs().max(1), ignore_index = True)

df1.index = df.index
print (df1)

     x    y    z
X  0.0  2.0  3.0
y  2.0  0.0  2.0
z  3.0  2.0  0.0
0 голосов
/ 21 января 2019

Вы можете использовать NumPy и передать массив в конструктор pd.DataFrame.Для небольшого количества строк, как в ваших данных, это должно быть эффективно.

A = df.values
res = pd.DataFrame(np.abs(A - A[:, None]).max(2),
                   index=df.index, columns=df.index.values)

print(res)

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