Каков наилучший способ написать функцию для вычисления построчных элементов в panda? - PullRequest
0 голосов
/ 13 мая 2018

У меня есть базовая таблица, например:

enter image description here

col1 - это столбец независимых значений, col2 - совокупность, основанная на комбинировании страны и типа. Я хочу вычислить столбцы от col3 до col5 со следующей логикой:

  1. col3: отношение элемента в col1 к общему количеству col1
  2. col4: отношение элемента в col1 к соответствующему элементу в col2
  3. col5: натуральный показатель произведения рядовых элементов в col3 и col4

Я написал такую ​​функцию, как показано ниже:

def calculate(df):
  for i in range(len(df)):
    df['col3'].loc[i] = df['col1'].loc[i]/sum(df['col1'])
    df['col4'].loc[i] = df['col1'].loc[i]/df['col2'].loc[i]
    df['col5'].loc[i] = np.exp(df['col3'].loc[i]*df['col4'].loc[i])
  return df

Эта функция выполняется и дает ожидаемые результаты, но ноутбук также выдает предупреждение:

SettingWithCopyWarning:

Значение пытается быть установлено для копии среза из DataFrame

См. Предостережения в документации: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

Я не уверен, пишу ли я здесь лучшую функцию. Любая помощь будет оценена! Спасибо.

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Цель векторизованных расчетов с pandas. Циклические вычисления возможны, но они неэффективны, потому что они не обрабатываются с непрерывными числовыми массивами.

col3: отношение элемента в col1 к общему количеству col1

df['col3'] = df['col1'] / df['col1'].sum()

col4: отношение элемента в col1 к соответствующему элементу в col2

df['col4'] = df['col1'] / df['col2']

col5: натуральный показатель произведения рядовых элементов в col3 и col4

df['col5'] = np.exp(df['col3'] * df['col4'])
0 голосов
/ 13 мая 2018

Я думаю, что apply и петли в пандах лучше избегать, поэтому лучше и быстрее использовать векторизованное решение:

df = pd.DataFrame({'col1':[4,5,4,5,5,4],
                   'col2':[7,8,9,4,2,3],
                   'col3':[1,3,5,7,1,0],
                   'col4':[5,3,6,9,2,4],
                   'col5':[1,4,3,4,0,4]})

print (df)
   col1  col2  col3  col4  col5
0     4     7     1     5     1
1     5     8     3     3     4
2     4     9     5     6     3
3     5     4     7     9     4
4     5     2     1     2     0
5     4     3     0     4     4

df['col3'] = df['col1']/(df['col1']).sum()
df['col4'] = df['col1']/df['col2']
df['col5'] = np.exp(df['col3']*df['col4'])
print (df)
   col1  col2      col3      col4      col5
0     4     7  0.148148  0.571429  1.088343
1     5     8  0.185185  0.625000  1.122705
2     4     9  0.148148  0.444444  1.068060
3     5     4  0.185185  1.250000  1.260466
4     5     2  0.185185  2.500000  1.588774
5     4     3  0.148148  1.333333  1.218391

Время :

df = pd.DataFrame({'col1':[4,5,4,5,5,4],
                   'col2':[7,8,9,4,2,3],
                   'col3':[1,3,5,7,1,0],
                   'col4':[5,3,6,9,2,4],
                   'col5':[1,4,3,4,0,4]})

#print (df)

#6000 rows
df = pd.concat([df] * 1000, ignore_index=True)

In [211]: %%timeit
     ...: df['col3'] = df['col1']/(df['col1']).sum()
     ...: df['col4'] = df['col1']/df['col2']
     ...: df['col5'] = np.exp(df['col3']*df['col4'])
     ...: 
1.49 ms ± 104 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

К сожалению, решение для цикла действительно медленное для этого образца, поэтому протестировано только в 60 rows DataFrame:

#60 rows
df = pd.concat([df] * 10, ignore_index=True)

In [3]: %%timeit
   ...: (calculate(df))
   ...: 
C:\Anaconda3\lib\site-packages\pandas\core\indexing.py:194: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self._setitem_with_indexer(indexer, value)
10.2 s ± 410 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...