如何将一列分成两列?

我有一列的数据框,我想分成两列,其中一列的标题为' fips' ,另一'row'

我的数据框df看起来像这样:

  row 0 00000 UNITED STATES 1 01000 ALABAMA 2 01001 Autauga County, AL 3 01003 Baldwin County, AL 4 01005 Barbour County, AL 

我不知道如何使用df.row.str[:]来实现分割行单元格的目标。 我可以使用df['fips'] = hello添加一个新列,并用hello填充它。 有任何想法吗?

  fips row 0 00000 UNITED STATES 1 01000 ALABAMA 2 01001 Autauga County, AL 3 01003 Baldwin County, AL 4 01005 Barbour County, AL 

可能有更好的办法,但这是一个办法:

 In [34]: import pandas as pd In [35]: df Out[35]: row 0 00000 UNITED STATES 1 01000 ALABAMA 2 01001 Autauga County, AL 3 01003 Baldwin County, AL 4 01005 Barbour County, AL In [36]: df = pd.DataFrame(df.row.str.split(' ',1).tolist(), columns = ['flips','row']) In [37]: df Out[37]: flips row 0 00000 UNITED STATES 1 01000 ALABAMA 2 01001 Autauga County, AL 3 01003 Baldwin County, AL 4 01005 Barbour County, AL 

TL; DR版本:

对于简单的情况:

  • 我有一个分隔符的文本列,我想要两列

最简单的解决scheme是:

 df['A'], df['B'] = df['AB'].str.split(' ', 1).str 

或者,您可以创build一个DataFrame自动创build与一列的每个条目自动与:

 df['AB'].str.split(' ', 1, expand=True) 

请注意,在这两种情况下, .tolist()方法都是不必要的。 zip()都不是。

详细:

Andy Hayden的解决scheme在演示str.extract()方法的function方面非常出色。

但是对于一个已知分隔符的简单分割(比如,用破折号分割或者用空格分割) .str.split()方法就足够了1 。 它在string的列(系列)上运行,并返回列表(系列):

 >>> import pandas as pd >>> df = pd.DataFrame({'AB': ['A1-B1', 'A2-B2']}) >>> df AB 0 A1-B1 1 A2-B2 >>> df['AB_split'] = df['AB'].str.split('-') >>> df AB AB_split 0 A1-B1 [A1, B1] 1 A2-B2 [A2, B2] 

1:如果你不确定.str.split()的前两个参数是做什么的,我推荐使用纯Python版本的文档。

但你怎么从:

  • 一个包含两个元素列表的列

至:

  • 两列,每列都包含列表的相应元素?

那么,我们需要仔细看一下列的.str属性。

这是一个神奇的对象,用于收集将列中每个元素作为string对待的方法,然后尽可能高效地在每个元素中应用相应的方法:

 >>> upper_lower_df = pd.DataFrame({"U": ["A", "B", "C"]}) >>> upper_lower_df U 0 A 1 B 2 C >>> upper_lower_df["L"] = upper_lower_df["U"].str.lower() >>> upper_lower_df UL 0 A a 1 B b 2 C c 

但它也有一个“索引”接口,通过它的索引获取string的每个元素:

 >>> df['AB'].str[0] 0 A 1 A Name: AB, dtype: object >>> df['AB'].str[1] 0 1 1 2 Name: AB, dtype: object 

当然,这个.str索引接口并不关心它索引的每个元素是否是一个string,只要它可以被索引,那么:

 >>> df['AB'].str.split('-', 1).str[0] 0 A1 1 A2 Name: AB, dtype: object >>> df['AB'].str.split('-', 1).str[1] 0 B1 1 B2 Name: AB, dtype: object 

然后,利用Python元组解开iterables来做一件简单的事

 >>> df['A'], df['B'] = df['AB'].str.split('-', 1).str >>> df AB AB_split AB 0 A1-B1 [A1, B1] A1 B1 1 A2-B2 [A2, B2] A2 B2 

当然,获取DataFrame分割一列string非常有用, .str.split()方法可以通过expand=True参数为您执行:

 >>> df['AB'].str.split('-', 1, expand=True) 0 1 0 A1 B1 1 A2 B2 

所以,完成我们想要的另一种方法是做:

 >>> df = df[['AB']] >>> df AB 0 A1-B1 1 A2-B2 >>> df.join(df['AB'].str.split('-', 1, expand=True).rename(columns={0:'A', 1:'B'})) AB AB 0 A1-B1 A1 B1 1 A2-B2 A2 B2 

你可以使用正则expression式很好地提取不同的部分:

 In [11]: df.row.str.extract('(?P<fips>\d{5})((?P<state>[AZ ]*$)|(?P<county>.*?), (?P<state_code>[AZ]{2}$))') Out[11]: fips 1 state county state_code 0 00000 UNITED STATES UNITED STATES NaN NaN 1 01000 ALABAMA ALABAMA NaN NaN 2 01001 Autauga County, AL NaN Autauga County AL 3 01003 Baldwin County, AL NaN Baldwin County AL 4 01005 Barbour County, AL NaN Barbour County AL [5 rows x 5 columns] 

解释这个有点长的正则expression式:

 (?P<fips>\d{5}) 
  • 匹配五位数字( \d )并将其命名为"fips"

下一部分:

 ((?P<state>[AZ ]*$)|(?P<county>.*?), (?P<state_code>[AZ]{2}$)) 

是否( | )两件事之一:

 (?P<state>[AZ ]*$) 
  • 匹配任何数字( * )的大写字母或空格( [AZ ] ),并在string( $ )结束之前将这个"state"

要么

 (?P<county>.*?), (?P<state_code>[AZ]{2}$)) 
  • 匹配其他任何( .* )然后
  • 一个逗号和一个空格
  • 匹配string( $ )结束之前的两位数字state_code

在这个例子中:
请注意,前两行命中“状态”(在县和state_code列中留下NaN),而最后三个命中县state_code(在状态列中留下NaN)。

如果您不想创build新的数据框,或者您的数据框的列数多于要分割的数据列数,则可以:

 df["flips"], df["row_name"] = zip(*df["row"].str.split().tolist()) del df["row"]