我正在尝试apply
DataFrames
个行中的函数(使用apply
和axis=1
)。该函数返回具有2维的NDArray。我希望将apply
返回到恰好包含2D NDArrays的单个对象列,但我得到:
<venv>/lib/python2.7/site-packages/pandas/core/frame.pyc in _homogenize(data, index, dtype)
5544 v = lib.fast_multiget(v, oindex.values, default=NA)
5545 v = _sanitize_array(v, index, dtype=dtype, copy=False,
-> 5546 raise_cast_failure=False)
5547
5548 homogenized.append(v)
<venv>/lib/python2.7/site-packages/pandas/core/series.pyc in _sanitize_array(data, index, dtype, copy, raise_cast_failure)
2918 elif subarr.ndim > 1:
2919 if isinstance(data, np.ndarray):
-> 2920 raise Exception('Data must be 1-dimensional')
2921 else:
2922 subarr = _asarray_tuplesafe(data, dtype=dtype)
Exception: Data must be 1-dimensional
有没有办法告诉Pandas不要试图解开阵列?
更新示例:
arr = np.ones((3,3))
pd.DataFrame({'d': [arr, arr]}).apply(lambda x: x.ix['d'], axis=1)
答案 0 :(得分:0)
在一个系列上运行apply
并用多维对象填充它可以正常工作
pd.Series([1, 2]).apply(lambda x: np.array([[x, x], [x, x]]))
0 [[1, 1], [1, 1]]
1 [[2, 2], [2, 2]]
dtype: object
但是,在数据帧上,pandas期望返回值为标量或一维
考虑数据框df
df = pd.DataFrame([[1, 2]])
这有效
df.apply(lambda x: 1)
0 1
1 1
dtype: int64
这个
df.apply(lambda x: [1])
0 1
0 1 1
这个
df.apply(lambda x: [1] * 2)
0 [1, 1]
1 [1, 1]
dtype: object
请注意,当我们返回一个长度为1
的列表时,它返回了一个数据帧,但是当我们返回一个长度大于1
的列表时,它又恢复为一系列列表。
<强> HOLDON! 强>
让我们加倍df
df = pd.DataFrame([[1, 2]] * 2)
并运行同样的事情
df.apply(lambda x: [1] * 2)
0 1
0 0 0
1 0 0
哇!好吧,所以我在两个不同的数据帧上运行相同的东西。看起来当返回值的长度与数据帧的off维度匹配时,pandas假定将返回值与off维度索引匹配。
我们可以用pd.Series
覆盖它,其中pandas将放弃其解释并使用它给出的系列索引。
df.apply(lambda x: pd.Series([1] * 5))
0 1
0 1 1
1 1 1
2 1 1
3 1 1
4 1 1
那么ndarray
呢这打破了
df.apply(lambda x: np.ones((3, 2)))
Exception: Data must be 1-dimensional
这可行,但不是你想要的
df.apply(lambda x: np.ones((3, 2)).tolist())
0 [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]
1 [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]
dtype: object
相反,我会使用传递的索引
来说明pd.Series
的理解
f = lambda x: np.ones((3, 2))
pd.Series([f(c) for _, c in df.iteritems()], df.columns)
0 [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]
1 [[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]
dtype: object
注意:
type(pd.Series([f(c) for _, c in df.iteritems()], df.columns).iloc[0])
numpy.ndarray