熊猫应用于以列表为值的数据框

时间:2018-07-19 10:07:54

标签: python pandas dataframe

我有一个包含两列的数据框,列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一起使用

我尝试使用broadcastreduce的apply参数,但没有成功。

问题:

  • 在我的熊猫版本中,是否存在适用于此目的的有效语法?
  • 是否有任何失败的见解?
  • 还有更好的解决方案/方法,也可以使用numpy或其他pandas函数吗?我目前的解决方案一点都不完美

3 个答案:

答案 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