通过分隔符拆分pandas数据帧列

140

我有一个小的样本数据:

import pandas as pd

df = {'ID': [3009, 129, 119, 120, 121, 122, 130, 3014, 266, 849, 174, 844],
  'V': ['IGHV7-B*01', 'IGHV7-B*01', 'IGHV6-A*01', 'GHV6-A*01', 'IGHV6-A*01',
        'IGHV6-A*01', 'IGHV4-L*03', 'IGHV4-L*03', 'IGHV5-A*01', 'IGHV5-A*04',
        'IGHV6-A*02','IGHV6-A*02'],
  'Prob': [1, 1, 0.8, 0.8056, 0.9, 0.805, 1, 1, 0.997, 0.401, 1, 1]}

df = pd.DataFrame(df)

看起来像是

df    

Out[25]: 
      ID    Prob           V
0    3009  1.0000  IGHV7-B*01
1     129  1.0000  IGHV7-B*01
2     119  0.8000  IGHV6-A*01
3     120  0.8056  IGHV6-A*01
4     121  0.9000  IGHV6-A*01
5     122  0.8050  IGHV6-A*01
6     130  1.0000  IGHV4-L*03
7    3014  1.0000  IGHV4-L*03
8     266  0.9970  IGHV5-A*01
9     849  0.4010  IGHV5-A*04
10    174  1.0000  IGHV6-A*02
11    844  1.0000  IGHV6-A*02

我想通过“-”分隔符拆分列“V”,并将其移动到另一个名为“allele”的列中

    Out[25]: 
      ID    Prob      V    allele
0    3009  1.0000  IGHV7    B*01
1     129  1.0000  IGHV7    B*01
2     119  0.8000  IGHV6    A*01
3     120  0.8056  IGHV6    A*01
4     121  0.9000  IGHV6    A*01
5     122  0.8050  IGHV6    A*01
6     130  1.0000  IGHV4    L*03
7    3014  1.0000  IGHV4    L*03
8     266  0.9970  IGHV5    A*01
9     849  0.4010  IGHV5    A*04
10    174  1.0000  IGHV6    A*02
11    844  1.0000  IGHV6    A*02

我尝试的代码不完整且没有起作用:

df1 = pd.DataFrame()
df1[['V']] = pd.DataFrame([ x.split('-') for x in df['V'].tolist() ])
或者
df.add(Series, axis='columns', level = None, fill_value = None)
newdata = df.DataFrame({'V':df['V'].iloc[::2].values, 
                        'Allele': df['V'].iloc[1::2].values})
3个回答

222

使用具有 expand=True 的向量化 str.split

In [42]:
df[['V','allele']] = df['V'].str.split('-',expand=True)
df

Out[42]:
      ID    Prob      V allele
0   3009  1.0000  IGHV7   B*01
1    129  1.0000  IGHV7   B*01
2    119  0.8000  IGHV6   A*01
3    120  0.8056   GHV6   A*01
4    121  0.9000  IGHV6   A*01
5    122  0.8050  IGHV6   A*01
6    130  1.0000  IGHV4   L*03
7   3014  1.0000  IGHV4   L*03
8    266  0.9970  IGHV5   A*01
9    849  0.4010  IGHV5   A*04
10   174  1.0000  IGHV6   A*02
11   844  1.0000  IGHV6   A*02

3
我尝试了这个,但我想将我的列分成三列。 df[['ColumnTable','Database','Schema','Table']] = df['ColumnTable'].str.split('.',expand=True) print(df) 我收到了一个错误消息: File "C:\Users\xxx\Anaconda3\lib\site-packages\pandas\core\frame.py", line 3189, in _setitem_array raise ValueError("Columns must be same length as key") ValueError: 列的数量必须和键的数量相同。 - DataGirl
3
@DataGirl 我有同样的问题。还尝试了列表推导式。问题的根源是我的值由元组组成。将它们转换为字符串解决了所有问题。所以 df[["x", "y"]] = df["x, y"].astype("string").str.split(", ", expand=True) - marianoju
@marianoju - 我会试一下。 - DataGirl
有没有一种方法可以处理列的值为NaN的情况(考虑我们想要保留NaN值)? - Jasmine Latendresse
在我的代码中按照这种方式使用会出现带有复制警告的设置。df[['V','allele']] = df['V'].str.split('-',expand=True).copy() 对我很有效。 - Liz

44

要将数据存储到新的数据框中,请使用相同的方法,只需将其用于新的数据框:

tmpDF = pd.DataFrame(columns=['A','B'])
tmpDF[['A','B']] = df['V'].str.split('-', expand=True)

最终(对我的目的更有用)如果您只需要获取字符串值的一部分(即“ - ”之前的文本),则可以使用.str.split(...)。str [idx],例如:

.str.split(...)。str [idx]

df['V'] = df['V'].str.split('-').str[0]
df
    ID      V       Prob
0   3009    IGHV7   1.0000
1   129     IGHV7   1.0000
2   119     IGHV6   0.8000
3   120     GHV6    0.8056
- 根据分隔符'-'将'V'值拆分为列表,并将第一个项目存储回列中

如果df['V'].str.split('-')返回一个列表,为什么我们需要使用字符串访问器来索引列表组件?我的假设是df['V'].str.split('-')[0]就足够了。 - lakeside

7
请使用以下内容:
df['allele'] = [x.split('-')[-1] for x in df['V']]

以上第一部分保留“-”符号后的任何值。
df['V'] = [x.split('-')[-0] for x in df['V']]

以上第二部分保留“-”符号前的任何值,并自动替换主列。
df.head(3)

我看到这是你的第一次贡献,感谢你的回答。如果你能解释一下你的方法如何工作以及为什么选择这种方法,那将会极大地改善它。当前,它不太可能得到太多赞赏,甚至可能被删除。 - Bracken
这对我有用。但是,我想知道是否有更有效的方法来完成这个任务并避免使用循环。 - Janzaib M Baloch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接