我有一个包含两列的数据框,列A
是整数列表,列B
包含整数。
我想要的输出是一个pandas系列,其值为列表,是通过将A
中列表中的每个元素乘以列B
中的相应元素而获得的。
我尝试使用apply
,但行为异常。
设置1:
如果A
发生中的列表的最大长度等于DataFrame的列数,那么我得到的结果是具有原始形状的DataFrame,而不是TimeSeries
ts1 = pd.Series([[1, 2], [3], [4, 5]])
ts2 = pd.Series([1, 2, 3])
df = pd.concat([ts1, ts2], keys=['A', 'B'], axis=1)
def foo(x):
return [el * x['B'] for el in x['A']]
df.apply(foo, axis=1)
A B
0 1 2
1 6 6
2 12 15
设置2:
对于A
中列表的任意长度(这是我的用例),apply
失败:
ts1 = pd.Series([[1, 2], [3], [4, 5, 6]])
ts2 = pd.Series([1, 2, 3])
df = pd.concat([ts1, ts2], keys=['A', 'B'], axis=1)
def foo(x):
return [el * x['B'] for el in x['A']]
df.apply(foo, axis=1, reduce=False)
ValueError: could not broadcast input array from shape (3) into shape (2)
我正在将pandas 0.21.1与python 3.4一起使用
我尝试使用broadcast
和reduce
的apply参数,但没有成功。
问题:
答案 0 :(得分:1)
在pandas 0.23.1
中对我来说效果很好:
s = df.apply(foo, axis=1)
print (s)
0 [1, 2]
1 [6]
2 [12, 15, 18]
dtype: object
另一种解决方案是将zip
列放在一起,并使用列表推导。不幸的是,pandas无法使用列表,Series
中的字典很好,大多数功能都失败了。此外,numpy
需要相同长度的列表才能进行转换2d numpy array
。
zipped = zip(df['A'], df['B'])
a = pd.Series([[el * j for el in i] for i, j in zipped], index=df.index)
print (a)
0 [1, 2]
1 [6]
2 [12, 15, 18]
dtype: object
答案 1 :(得分:1)
您可以使用tuple
来解决。通常,Pandas不能很好地将列表作为系列元素使用。不建议您这样做,也不要对操作进行矢量化处理。
def foo(x):
return tuple([i * x['B'] for i in x['A']])
df.apply(foo, axis=1).apply(list)
0 [1, 2]
1 [6]
2 [12, 15]
dtype: object
或升级到Pandas v0.23。
答案 2 :(得分:1)
您还可以将列表转换为numpy数组,并在两个系列中使用广播
df.A.apply(np.array) * df.B
#Out:
0 [1, 2]
1 [6]
2 [12, 15]
dtype: object