我有一些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数组
这怎么办?
答案 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
获得。
接受的答案仍然存在,因为它回答了原始问题,但这是一个更好的做法。