如何将一列拆分为两列?

2024-05-13 07:02:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个带有一列的数据框,我想将它分成两列,一列的标题是'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

Tags: 数据标题hellodfunitedrowalstates
3条回答

也许有更好的方法,但这里有一种方法:

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

您可以使用regex模式非常灵活地extract出不同的部分:

In [11]: df.row.str.extract('(?P<fips>\d{5})((?P<state>[A-Z ]*$)|(?P<county>.*?), (?P<state_code>[A-Z]{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]

要解释有点长的regex:

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

下一部分:

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

做两件事中的任何一件:

(?P<state>[A-Z ]*$)
  • 匹配任意数字(*)的大写字母或空格([A-Z ]),并在字符串结尾($)之前将其命名为"state"

或者

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

在示例中:
注意,前两行命中“state”(将NaN留在county和state_code列中),而最后三行命中county和state_code(将NaN留在state列中)。

TL;DR版本:

对于以下简单情况:

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

最简单的解决方案是:

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

或者,可以创建一个数据框,其中每个拆分条目都有一列,并自动使用:

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

如果字符串的拆分数不一致,并且希望None替换丢失的值,则必须使用expand=True

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

详细说明:

Andy Hayden's solution在演示^{}方法的威力方面最为出色。

但是对于在已知分隔符上的简单拆分(例如,用破折号拆分或用空白拆分),使用^{}方法就足够了。它对字符串的列(序列)进行操作,并返回列表的列(序列):

>>> 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()的前两个参数的作用, 我推荐plain Python version of the method的文档。

但你如何从:

  • 包含两个元素列表的列

致:

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

好吧,我们需要更仔细地看一下列的.str属性。

它是一个神奇的对象,用于收集将列中的每个元素视为字符串的方法,然后尽可能高效地在每个元素中应用相应的方法:

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

   U  L
0  A  a
1  B  b
2  C  c

但它也有一个“索引”接口,用于按索引获取字符串的每个元素:

>>> 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的这个索引接口并不真正关心它所索引的每个元素是否实际上是一个字符串,只要它可以被索引,那么:

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

那么,利用iterables的Python元组解包就很简单了

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

      AB  AB_split   A   B
0  A1-B1  [A1, B1]  A1  B1
1  A2-B2  [A2, B2]  A2  B2

当然,从拆分字符串列中获取数据帧非常有用,因此.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   A   B
0  A1-B1  A1  B1
1  A2-B2  A2  B2

虽然expand=True版本较长,但与元组解包方法相比有明显的优势。元组解包不能很好地处理不同长度的拆分:

>>> df = pd.DataFrame({'AB': ['A1-B1', 'A2-B2', 'A3-B3-C3']})
>>> df
         AB
0     A1-B1
1     A2-B2
2  A3-B3-C3
>>> df['A'], df['B'], df['C'] = df['AB'].str.split('-')
Traceback (most recent call last):
  [...]    
ValueError: Length of values does not match length of index
>>> 

但是expand=True通过在没有足够“拆分”的列中放置None来很好地处理它:

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

相关问题 更多 >