pandas назначить результат из списка столбцов - PullRequest
2 голосов
/ 23 апреля 2020

Предположим, у меня есть кадр данных, как показано ниже:

import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({'A':np.random.randn(5), 'B': np.zeros(5), 'C': np.zeros(5)})
df
>>>
          A    B    C
0  0.496714  0.0  0.0
1 -0.138264  0.0  0.0
2  0.647689  0.0  0.0
3  1.523030  0.0  0.0
4 -0.234153  0.0  0.0

И у меня есть список столбцов, которые я хочу заполнить значением 1, когда A отрицательно.

idx = df.A < 0
cols = ['B', 'C']

Так что в этом случае Я хочу, чтобы индексы [1, 'B'] и [4, 'C'] были установлены на 1.

Что я пробовал :

Однако выполнение df.loc[idx, cols] = 1 устанавливает всю строку равной 1, а не только отдельный столбец. Я также попытался сделать df.loc[idx, cols] = pd.get_dummies(cols), который дал результат:

          A    B    C
0  0.496714  0.0  0.0
1 -0.138264  0.0  1.0
2  0.647689  0.0  0.0
3  1.523030  0.0  0.0
4 -0.234153  NaN  NaN

Я предполагаю, что это потому, что индекс get_dummies и кадр данных не совпадают.

Ожидается Вывод:

          A    B    C
0  0.496714  0.0  0.0
1 -0.138264  1.0  0.0
2  0.647689  0.0  0.0
3  1.523030  0.0  0.0
4 -0.234153  0.0  1.0

Итак, каков наилучший (читай быстрее) способ сделать это. В моем случае это 1000 строк и 5 столбцов.

Время получения результатов:

TLDR: редактирование значений выполняется быстрее.

%%timeit
df.values[idx, df.columns.get_indexer(cols)] = 1

123 мкс ± 2,5 мкс на л oop (среднее ± стандартное отклонение из 7 прогонов, 10000 циклов каждый)

%%timeit
df.iloc[idx.array,df.columns.get_indexer(cols)]=1

266 мкс ± 7 мкс на 1 oop (среднее ± стандартное отклонение из 7 прогонов) 1000 петель каждая)

Ответы [ 2 ]

3 голосов
/ 23 апреля 2020

Используйте numpy индексирование для повышения производительности:

idx = df.A < 0
res = ['B', 'C']
arr = df.values
arr[idx, df.columns.get_indexer(res)] = 1
print (arr)
[[ 0.49671415  0.          0.        ]
 [-0.1382643   1.          0.        ]
 [ 0.64768854  0.          0.        ]
 [ 1.52302986  0.          0.        ]
 [-0.23415337  0.          1.        ]]

df = pd.DataFrame(arr, columns=df.columns, index=df.index)
print (df)
          A    B    C
0  0.496714  0.0  0.0
1 -0.138264  1.0  0.0
2  0.647689  0.0  0.0
3  1.523030  0.0  0.0
4 -0.234153  0.0  1.0

Альтернатива:

idx = df.A < 0
res = ['B', 'C']
df.values[idx, df.columns.get_indexer(res)] = 1
print (df)
          A    B    C
0  0.496714  0.0  0.0
1 -0.138264  1.0  0.0
2  0.647689  0.0  0.0
3  1.523030  0.0  0.0
4 -0.234153  0.0  1.0
1 голос
/ 23 апреля 2020
ind = df.index[idx]
for idx,col in zip(ind,res):
   ...:     df.at[idx,col] = 1

In [7]: df
Out[7]:
          A    B    C
0  0.496714  0.0  0.0
1 -0.138264  1.0  0.0
2  0.647689  0.0  0.0
3  1.523030  0.0  0.0
4 -0.234153  0.0  1.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...