Управление списками в столбце кадра данных pandas (например, разделение на другой столбец) - PullRequest
0 голосов
/ 28 мая 2020

У меня есть кадр данных pandas с одним столбцом, содержащим списки. Я хочу sh разделить каждый элемент списка в каждой строке на скалярное значение в другом столбце. В следующем примере я wi sh, чтобы разделить каждый элемент в a на b:

              a   b
0  [11, 22, 33]  11
1  [12, 24, 36]   2
2  [33, 66, 99]   3

Таким образом получится следующий результат:

              a   b                   c
0  [11, 22, 33]  11     [1.0, 2.0, 3.0]
1  [12, 24, 36]   2   [6.0, 12.0, 18.0]
2  [33, 66, 99]   3  [11.0, 22.0, 33.0]

Я могу добиться этого следующим кодом:

import pandas as pd

df = pd.DataFrame({"a":[[11,22,33],[12,24,36],[33,66,99]], "b" : [11,2,3]})

result = {"c":[]}
for _, row in df.iterrows():
    result["c"].append([x / row["b"] for x in row["a"]])

df_c = pd.DataFrame(result)
df = pd.concat([df,df_c], axis="columns")

Но явная итерация по строкам и сбор результата в словаре, преобразование его в фрейм данных и затем конкатенация в исходный фрейм данных кажутся очень неэффективными и inelegant .

Есть ли у кого-нибудь лучшее решение?

Заранее спасибо и ура!


PS : Если вам интересно, зачем мне хранить списки в столбце: это результирующие амплитуды преобразования Фурье.

Почему я не использую один столбец для каждой частоты?

  1. Создание нового столбца для каждой частоты происходит ужасно медленно
  2. При разных частотах дискретизации и размерах окна БПФ в моем проекте существует несколько наборов частот.

Ответы [ 2 ]

2 голосов
/ 28 мая 2020

заархивируйте два столбца, разделите каждую запись в столбце a с соответствующей записью в столбце b с помощью комбинации product и starmap и преобразуйте итератор обратно в список .

from itertools import product,starmap
from operator import floordiv
df['c'] = [list(starmap(floordiv,(product(num,[denom])))) 
           for num, denom in zip(df.a,df.b)]


        a           b       c
0   [11, 22, 33]    11  [1, 2, 3]
1   [12, 24, 36]    2   [6, 12, 18]
2   [33, 66, 99]    3   [11, 22, 33]

В качестве альтернативы вы могли бы просто использовать массив numpy внутри итерации:

df['c'] = [list(np.array(num)/denom) for num, denom in zip(df.a,df.b)]

Спасибо @jezrael за предложение - все это может быть ненужным, поскольку у scipy есть что-то для FFT - посмотрите ссылку и посмотрите, поможет ли.

1 голос
/ 28 мая 2020

Я бы преобразовал списки в numpy массивы:

df['c'] = df['a'].apply(np.array) / df['b']

Вы получите np.array s в столбце c. Если вам действительно нужны списки, вам придется их конвертировать обратно

df['c'] = df['c'].apply(list)
...