Pandas中Str列的最小值

时间:2018-02-08 16:27:22

标签: python pandas

我有一个数据框,其中一列包含值列表,例如

dict = {'a' : [0, 1, 2], 'b' : [4, 5, 6]}
df = pd.DataFrame(dict)
df.loc[:, 'c'] = -1
df['c'] = df.apply(lambda x: [x.a, x.b], axis=1)

所以我得到了:

   a  b       c
0  0  4  [0, 4]
1  1  5  [1, 5]
2  2  6  [2, 6]

我现在想在新列d中保存列c的每个条目的最小值,这应该给我以下数据框:

   a  b       c    d
0  0  4  [0, 4]    0
1  1  5  [1, 5]    1
2  2  6  [2, 6]    2

虽然我总是不能用min()或类似的方法做到这一点。现在我正在使用df.apply(lambda x:min(x [' c'],轴= 1)。但在我的情况下这太慢了。你知道更快的方法吗? ? 谢谢!

3 个答案:

答案 0 :(得分:3)

你可以从numpy获得帮助:

import numpy as np 

df['d'] = np.array(df['c'].tolist()).min(axis=1)

如评论中所述,如果您不需要列c,那么:

df['d'] = df[['a','b']].min(axis=1)

答案 1 :(得分:2)

请记住,系列(如df['c'])是可迭代的。然后,您可以创建一个新列表并将其设置为键,就像您使用字典一样。该列表将自动转换为pd.Series对象。除非您正在处理真正(非常)大数据,否则无需使用花哨的pandas函数。

df['d'] = [min(c) for c in df['c']]

编辑:更新以下评论

df['d'] = [min(c, key=lambda v: v - df.a) for c in df['c']]

这不起作用,因为v是一个值(在第一次迭代中传递0,然后传递4)。 df.a是一个系列。 v - df.a是一个包含元素[v - df.a[0], v - df.a[1], ...]的新系列。然后min尝试比较这些系列键,这没有任何意义,因为它将测试if True, False, ...]或类似pandas引发错误的那些,因为它不会真有意义。你需要的是

df['d'] = [min(c, key=lambda v: v - df['a'][i]) for i, c in enumerate(df['c'])]  
# I prefer to use df['a'] rather than df.a

所以你依次从df['a']而不是整个系列v获取df['a']的每个

然而,在计算最小值时取一个常数绝对没有任何作用,但我猜这是从你实际做的那里简化的。上面的两个样本将完全相同。

答案 2 :(得分:2)

这是一个功能性解决方案。

df['d'] = list(map(min, df['c']))

它的工作原因是:

  • df['c']pd.Series,是一个可迭代的对象。
  • map是一个惰性运算符,它将函数应用于iterable的每个元素。
  • 由于map是懒惰的,我们必须应用list才能分配系列。