Итерация по списку в столбце Pandas DataFrame - PullRequest
1 голос
/ 24 марта 2020

У меня есть фрейм данных df как этот:

                                                  my_list
Index                                                                
0                                               [81310, 81800]
1                                                      [82160]
2            [75001, 75002, 75003, 75004, 75005, 75006, 750...
3                                                      [95190]
4                                               [38170, 38180]
5                                                      [95240]
6                                                      [71150]
7                                                      [62520]

У меня есть список с именем code, содержащий хотя бы один элемент.

code = ['75008', '75015']

Я хочу создать другой столбец в моем DataFrame с именем my_min, содержащий минимальную абсолютную разницу между каждым элементом списка code и списком из df.my_list.

Вот команды, которые я пробовал:

df.loc[:, 'my_list'] = min([abs(int(x)-int(y)) for x in code for y in df.loc[:, 'my_list'].str[:]])
>>> TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

#or

df.loc[:, 'my_list'] = min([abs(int(x)-int(y)) for x in code for y in df.loc[:, 'my_list']])
>>> TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

#or

df.loc[:, 'my_list'] = min([abs(int(x)-int(y)) for x in code for y in df.loc[:, 'my_list'].tolist()])
>>> TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

#or

df.loc[:, 'my_list'] = min([abs(int(x)-int(y)) for x in code for y in z for z in df.loc[:, 'my_list'].str[:]])
>>> UnboundLocalError: local variable 'z' referenced before assignment

#or

df.loc[:, 'my_list'] = min([abs(int(x)-int(y)) for x in code for y in z for z in df.loc[:, 'my_list']])
>>> UnboundLocalError: local variable 'z' referenced before assignment

#or

df.loc[:, 'my_list'] = min([abs(int(x)-int(y)) for x in code for y in z for z in df.loc[:, 'my_list'].tolist()])
>>> UnboundLocalError: local variable 'z' referenced before assignment

Ответы [ 3 ]

1 голос
/ 24 марта 2020

вы можете сделать это с помощью списка:

import pandas as pd
import numpy as np
df = pd.DataFrame({'my_list':[[81310, 81800],[82160]]})

code = ['75008', '75015']

pd.DataFrame({'my_min':[min([abs(int(i) - j) for i in code for j in x]) 
              for x in df.my_list]})

возвращает

   my_min
0    6295
1    7145

Вы также можете использовать pd.Series.apply вместо внешнего списка, например:

df.my_list.apply(lambda x: min([abs(int(i) - j) for i in code for j in x]) )

1 голос
/ 24 марта 2020

Напишите помощника: def find_min(lst): - ясно, что вы знаете, как это сделать. Помощник свяжется с глобальным именем code.

Затем примените его:

df['my_min'] = df.my_list.apply(find_min)

Преимущество использования помощника заключается в том, что вы можете написать для него отдельные модульные тесты.

Если вы предпочитаете избегать глобалов, вы найдете partial весьма полезным. https://docs.python.org/3/library/functools.html#functools .partial

0 голосов
/ 24 марта 2020

Если у вас есть pandas 0.25+, вы можете использовать explode и комбинировать с np.min:

# sample data
df = pd.DataFrame({'my_list':
                  [[81310, 81800], [82160], [75001,75002]]})
code = ['75008', '75015']

# concatenate the lists into one series
s = df.my_list.explode()

# convert `code` into np.array
code = np.array(code, dtype=int)

# this is the output series
pd.Series(np.min(np.abs(s.values[:,None] - code),axis=1), 
          index=s.index).min(level=0)

Выход:

0    6295
1    7145
2       6
dtype: int64
...