如何在熊猫列中插入多维numpy数组?

时间:2019-06-16 10:43:42

标签: python arrays pandas numpy

我有一些numpy数组,其行数(轴= 0)与pandas数据框的行数相同。

我想在数据框中创建一个新列,为此,每个条目将是一个较小维度的numpy数组。

代码:

    some_df = pd.DataFrame(columns=['A'])
    for i in range(10):
        some_df.loc[i] = [np.random.rand(4, 6, 8)

    data = np.stack(some_df['A'].values)  #shape (10, 4, 6, 8)
    processed = np.max(data, axis=1)  # shape (10, 6, 8)

    some_df['B'] = processed  # This fails

我希望新列'B'包含形状为(6, 8)的numpy数组

这怎么办?

3 个答案:

答案 0 :(得分:2)

由于不推荐使用,因此疼痛,缓慢且后期处理并不容易。

一种可能的解决方案是使用列表理解:

some_df['B'] = [x for x in processed]

或转换为列表并分配:

some_df['B'] = processed.tolist()

答案 1 :(得分:0)

我知道这个问题已经有了答案,但我想添加一种更具可扩展性的方法来做到这一点。正如上面的评论中提到的,通常不建议将数组作为“字段”值存储在 pandas-Dataframe 列中(我实际上不知道为什么?)。尽管如此,在我的日常工作中,当处理时间序列数据和一堆相关的元数据时,这是一个非常重要的功能。 一般来说,我以 Pandas 数据帧的形式组织我的实验时间序列,其中一列包含相同长度的 numpy 数组,另一列包含有关某些测量条件等的元数据信息。

jezrael 提出的解决方案效果很好,我在过去 4 年里定期使用它。但是这种方法可能会遇到巨大的内存问题。在我的情况下,我遇到了这些问题,处理超过 500 万行的数据帧和大约 500 万行的时间序列。 100 个数据点。

这些问题的解决方案非常简单,因为我没有在任何地方找到它,我只想在这里分享它:只需将您的 2D 数组转换为 pandas-Series 对象并将其分配给数据框的列:

>
df["new_list_column"] = pd.Series(list(numpy_array_2D))

答案 2 :(得分:0)

2 年后回到这个问题,这是一个更好的做法:

from itertools import product, chain
import pandas as pd
import numpy as np
from typing import Dict


def calc_col_names(named_shape):
    *prefix, shape = named_shape
    names = [map(str, range(i)) for i in shape]
    return map('_'.join, product(prefix, *names))


def create_flat_columns_df_from_dict_of_numpy(
        named_np: Dict[str, np.array],
        n_samples_per_np: int,
):
    named_np_correct_lenth = {k: v for k, v in named_np.items() if len(v) == n_samples_per_np}
    flat_nps = [a.reshape(n_samples_per_np, -1) for a in named_np_correct_lenth.values()]
    stacked_nps = np.column_stack(flat_nps)
    named_shapes = [(name, arr.shape[1:]) for name, arr in named_np_correct_lenth.items()]
    col_names = [*chain.from_iterable(calc_col_names(named_shape) for named_shape in named_shapes)]
    df = pd.DataFrame(stacked_nps, columns=col_names)
    df = df.convert_dtypes()
    return df


def parse_series_into_np(df, col_name, shp):
    # can parse the shape from the col names
    n_samples = len(df)
    col_names = sorted(c for c in df.columns if col_name in c)
    col_names = list(filter(lambda c: c.startswith(col_name + "_") or len(col_names) == 1, col_names))
    col_as_np = df[col_names].astype(np.float).values.reshape((n_samples, *shp))
    return col_as_np

将 ndarray 放入 Dataframe 的用法:

full_rate_df = create_flat_columns_df_from_dict_of_numpy(
    named_np={name: np.array(d[name]) for name in ["name1", "name2"]},
    n_samples_per_np=d["name1"].shape[0]
)

其中 d 是相同 shape[0] 的 nd 个数组的字典,由 ["name1", "name2"] 散列。

反向操作可以通过parse_series_into_np获得。


接受的答案仍然存在,因为它回答了原始问题,但这是一个更好的做法。