对熊猫DataFrame中的列进行.str.split()操作后,获取最后一个“列”


80

我在pandas DataFrame中有一列想要在一个空格上拆分。使用进行拆分非常简单DataFrame.str.split(' '),但是我无法从最后一个条目中创建新列。当我.str.split()进入列时,我得到了一个数组列表,但我不知道如何操纵它来为我的DataFrame获取新列。

这是一个例子。列中的每个条目都包含“符号数据价格”,我想将价格分开(并在一半情况下最终删除“ p” ...或“ c”)。

import pandas as pd
temp = pd.DataFrame({'ticker' : ['spx 5/25/2001 p500', 'spx 5/25/2001 p600', 'spx 5/25/2001 p700']})
temp2 = temp.ticker.str.split(' ')

产生

0    ['spx', '5/25/2001', 'p500']
1    ['spx', '5/25/2001', 'p600']
2    ['spx', '5/25/2001', 'p700']

但是temp2[0]只给出一个列表项的数组temp2[:][-1]就会失败。如何将每个数组中的最后一个条目转换为新列?谢谢!

Answers:


151

做这个:

In [43]: temp2.str[-1]
Out[43]: 
0    p500
1    p600
2    p700
Name: ticker

因此,总计为:

>>> temp = pd.DataFrame({'ticker' : ['spx 5/25/2001 p500', 'spx 5/25/2001 p600', 'spx 5/25/2001 p700']})
>>> temp['ticker'].str.split(' ').str[-1]
0    p500
1    p600
2    p700
Name: ticker, dtype: object

6
爱干净的解决方案!
ericmjl 2014年

12
来自“熊猫”的作者:)
kmonsoor 2014年

5
我喜欢这个解决方案,但是它如何工作?意思是,“幕后”正在发生什么,允许其后方str括号从列表中选择特定元素?
凯文·马克汉姆

2
我对此有些困惑,单线是d1.ticker.str.split()。str [-1]。不是您所期望的...
citynorman

6
@KevinMarkham:它是这样工作的:str不仅适用于字符串,而且在某种程度上也适用于列表。因此,如果您有一个字符串Series,则将采用每个字符串的第一个字符,foo然后foo.str[0]采用最后一个字符foo.str[-1]。但是由于str也同样(部分地)适用于列表,因此temp2.str[-1]采用系列中每个列表的最后一个元素。毕竟,字符串是字符序列,类似于列表。
John Zwinck

46

您可以使用该tolist方法作为中介:

In [99]: import pandas as pd

In [100]: d1 = pd.DataFrame({'ticker' : ['spx 5/25/2001 p500', 'spx 5/25/2001 p600', 'spx 5/25/2001 p700']})

In [101]: d1.ticker.str.split().tolist()
Out[101]: 
[['spx', '5/25/2001', 'p500'],
 ['spx', '5/25/2001', 'p600'],
 ['spx', '5/25/2001', 'p700']]

从中可以制作新的DataFrame:

In [102]: d2 = pd.DataFrame(d1.ticker.str.split().tolist(), 
   .....:                   columns="symbol date price".split())

In [103]: d2
Out[103]: 
  symbol       date price
0    spx  5/25/2001  p500
1    spx  5/25/2001  p600
2    spx  5/25/2001  p700

从好的方面来说,您可以确定价格:

In [104]: d2["price"] = d2["price"].str.replace("p","").astype(float)

In [105]: d2
Out[105]: 
  symbol       date  price
0    spx  5/25/2001    500
1    spx  5/25/2001    600
2    spx  5/25/2001    700

PS:但是如果您真的只想最后一列,apply就足够了:

In [113]: temp2.apply(lambda x: x[2])
Out[113]: 
0    p500
1    p600
2    p700
Name: ticker

这只是帮助我在pandas中添加了一个日志文件,该文件太过可怕和凌乱,以至于以前都无法触摸(单列数据,每行包含大量信息)。
2016年

与Wes McKinney的答案相比,所有这些方法都具有灾难性的性能。
John Zwinck

3
@JohnZwinck:哇,关于性能的五年前答案仅与性能相关,这是在两个月前才引入的?那是..严谨的,我给你!
DSM

1
但这就是SE的意义:过时的答案应少显眼。因为如果OP不更改已接受的解决方案,这是不可能的,那么只有警告未来的用户才可以投票
。.– FooBar


4

使用熊猫0.20.3:

In [10]: import pandas as pd
    ...: temp = pd.DataFrame({'ticker' : ['spx 5/25/2001 p500', 'spx 5/25/2001 p600', 'spx 5/25/2001 p700']})
    ...:

In [11]: temp2 = temp.ticker.str.split(' ', expand=True)  # the expand=True return a DataFrame

In [12]: temp2
Out[12]:
     0          1     2
0  spx  5/25/2001  p500
1  spx  5/25/2001  p600
2  spx  5/25/2001  p700

In [13]: temp3 = temp.join(temp2[2])

In [14]: temp3
Out[14]:
               ticker     2
0  spx 5/25/2001 p500  p500
1  spx 5/25/2001 p600  p600
2  spx 5/25/2001 p700  p700

1

如果您正在寻找单线(就像我来这里一样),这应该做得很好:

temp2 = temp.ticker.str.split(' ', expand = True)[-1]

您还可以按如下方式简单地修改此答案,以将此列分配回原始DataFrame:

temp['last_split'] = temp.ticker.str.split(' ', expand = True)[-1]

我想这是一个很流行的用例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.