在Pandas.DataFrame的单元格中存储numpy.array

71

我有一个数据框,想要存储“原始”的numpy.array

df['COL_ARRAY'] = df.apply(lambda r: np.array(do_something_with_r), axis=1)

但看起来 pandas 似乎试图“拆开”numpy.array。

有没有其他方法?除了使用包装器(请参见下面的编辑)?

我尝试过 reduce=False,但没有成功。

编辑

这个方法可以解决,但我必须使用“虚拟”的Data类来包装数组,这是不令人满意和不太优美的。

class Data:
    def __init__(self, v):
        self.v = v

meas = pd.read_excel(DATA_FILE)
meas['DATA'] = meas.apply(
    lambda r: Data(np.array(pd.read_csv(r['filename'])))),
    axis=1
)
9个回答

71

使用一个包装器来封装numpy数组,即将numpy数组作为列表传递。

a = np.array([5, 6, 7, 8])
df = pd.DataFrame({"a": [a]})

输出:

             a
0  [5, 6, 7, 8]

或者你可以通过创建元组并使用 apply(np.array) 方法来完成,例如你有一个数据框:

df = pd.DataFrame({'id': [1, 2, 3, 4],
                   'a': ['on', 'on', 'off', 'off'],
                   'b': ['on', 'off', 'on', 'off']})

df['new'] = df.apply(lambda r: tuple(r), axis=1).apply(np.array)

输出:

     a    b  id            new
0   on   on   1    [on, on, 1]
1   on  off   2   [on, off, 2]
2  off   on   3   [off, on, 3]
3  off  off   4  [off, off, 4]
df['new'][0]

输出:

array(['on', 'on', '1'], dtype='<U2')

可以这样做,但我宁愿使用一个虚拟类而不是列表。 - Cedric H.
如果你使用 np.array([[1,2],[3,4]]) 这样的二维数组而不是 tuple(r),是否可以工作呢? - Cedric H.
"tuple(r)" 也适用于二维数组。你是不是想用 2D np.array 替换 "tuple(r)"? - Bharath M Shetty
是的。我的意思是,我理解你的解决方案,并且它有效,但是如果我想在“new”列中有一个2D np.array(而不是如图所示的1D数组),该怎么办? - Cedric H.
你能在问题中添加期望的输出吗?如果你想创建一个新的二维数组,那么行中的所有元素都应该是numpy数组。我的解决方案在这种情况下有效。如果它是混合类型,你必须先使用if else将其转换为numpy数组。 - Bharath M Shetty

30

如果您首先将列设置为类型对象,则可以插入没有任何包装的数组:

df = pd.DataFrame(columns=[1])
df[1] = df[1].astype(object)
df.loc[1, 1] = np.array([5, 6, 7, 8])
df

输出:

    1
1   [5, 6, 7, 8]

6
您可以使用方括号将数据框数据参数包装起来,以保持每个单元格中的np.array
one_d_array = np.array([1,2,3])
two_d_array = one_d_array*one_d_array[:,np.newaxis]
two_d_array

array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])


pd.DataFrame([
    [one_d_array],
    [two_d_array] ])

                                   0
0                          [1, 2, 3]
1  [[1, 2, 3], [2, 4, 6], [3, 6, 9]]

它们变成了 list 吗? - WestCoastProjects
1
@javadba 我将上面的输出设置为 df 并查看 print(type(df.iloc[0,0])) --> <class 'numpy.ndarray'> 这是 Pandas 0.23.0 版本。你在其他版本中看到了不同的东西吗? - user1717828
1
实际上你是正确的 - 更高票的答案之一让人觉得 ndarray 会被转换为列表。我刚刚测试了一下。without括号我们得到了df中的rows,而with括号我们得到了像你说的ndarrays。 - WestCoastProjects

2
将列的类型预设为object,这样可以直接存储NumPy数组。
df['COL_ARRAY'] = pd.Series(dtype='object')

df['COL_ARRAY'] = df.apply(lambda r: np.array(do_something_with_r), axis=1)

1
选择使用内置函数eval既易于使用又易于阅读。
# First ensure use object store str
df['col2'] = self.df['col2'].astype(object)
# read
arr_obj = eval(df.at[df[df.col_1=='xyz'].index[0], 'col2']))
# write
df.at[df[df.col_1=='xyz'].index[0], 'col2'] = str(arr_obj)

真实的商店展示完美的人类可读取的值:

col_1,  col_2
xyz,    "['aaa', 'bbb', 'ccc', 'ddd']"

通常使用 eval() 不是一个好主意。在字符串和代码之间自由转换不安全,并且会使 IDE/linter/type-checker/其他人阅读您的代码感到困惑。请考虑使用此帖子中提到的其他方法。 - vvolhejn

1
假设您有一个名为“ds”的DataFrame,并且它有一个名为“class”的列。如果“ds”['class']包含字符串或数字,并且您想要用“numpy.ndarray”或“list”进行更改,则以下代码将有所帮助。在代码中,“class2vector”是一个“numpy.ndarray”或“list”,而“ds_class”是一个筛选条件。
“ds['class'] = ds['class'].map(lambda x: class2vector if (isinstance(x, str) and (x == ds_class)) else x)”

0

这是我的两分贡献(在Python 3.7上测试过):

import pandas as pd
import numpy as np

dataArray = np.array([0.0, 1.0, 2.0])
df = pd.DataFrame()
df['User Col A'] = [1]
df['Array'] = [dataArray]

0

只需通过第一个 apply 将要存储的内容包装到一个 list 对象中,然后通过第二个 apply 提取该 listindex 0

import pandas as pd
import numpy as np

df = pd.DataFrame({'id': [1, 2, 3, 4],
                   'a': ['on', 'on', 'off', 'off'],
                   'b': ['on', 'off', 'on', 'off']})


df['new'] = df.apply(lambda x: [np.array(x)], axis=1).apply(lambda x: x[0])

df

输出:

    id  a       b       new
0   1   on      on      [1, on, on]
1   2   on      off     [2, on, off]
2   3   off     on      [3, off, on]
3   4   off     off     [4, off, off]

0

如果你只想要其中一些列,你可以这样做。以 @allenyllee 的示例为例,

df = pd.DataFrame({'id': [1, 2, 3, 4],
                   'a': ['on', 'on', 'off', 'off'],
                   'b': ['on', 'off', 'on', 'off']})

df['new'] = df[['a','b']].apply(lambda x: np.array(x), axis=1)

它的输出结果为

   id    a    b         new
0   1   on   on    [on, on]
1   2   on  off   [on, off]
2   3  off   on   [off, on]
3   4  off  off  [off, off]

如果您需要特定的顺序,也可以更改[['a','b']]的顺序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接