Pandas Dataframe:如何将一列拆分为多个onehotcoded列

2024-05-17 23:43:59 发布

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

我有一个这样的文本文件:

444537110                         3 11112111022002200022022111121222002...

输入文件中最后一个字段的长度为50k个字符,并且只有0、1或2个字符。我要一个热编码版本的最后一个字段。所以我的预期结果是这样的一个数据帧:

^{pr2}$

我通过读取输入文件创建了一个初始数据帧:

df = pd.read_csv('test.txt', index_col=0, sep='\s+', header=None, names = ['chip', 'genos'])

这将创建一个包含3列的数据帧,如下所示:

id        chip  genos
444537110    3  1111211102200220000022022111121222000200022002...

我想我可以使用下面的方法创建初始的单独列,然后使用pandas get_dummies函数进行一个热编码,但我无法创建单独的列。我试过了

[c for c in df['genos'].str]

但这并不是把人物分开

我在这里看到了一个类似的问题和答案:How can I one hot encode in Python?

但这只处理一个热编码,而不处理拆分一个非常大的列所带来的额外复杂性


Tags: 文件csv数据intest版本编码df
2条回答

记住@Dan对您的问题的评论,即您将以50k*3列结尾,您可以通过这样做获得您想要的输出:

string ="444537110 3 11112111022002200022022111121222002"
df = pd.DataFrame([string.split(" ")],columns=['id','chip','genos'])
max_number_of_genes = int(df.genos.apply(lambda x : len([y for y in x])).max())

#Create columns 
for gene in range(1,max_number_of_genes+1):
    for y in range(4):
        df['g{}_{}'.format(gene, y)] = 0

#Iterating over genos values 
for row_number, row in df.iterrows():
    genos = [int(x) for x in df.iloc[row_number, 2]]
    for gene_number, gene in enumerate(genos):     
        df.loc[row_number, 'g{}_{}'.format(gene_number+1, gene)] = 1 

print(df)

输出

^{pr2}$

首先用convert string to list创建DataFrame,然后调用^{}

df1 = pd.DataFrame([list(x) for x in df['genos']], index=df.index).add_prefix('g')
df2 = pd.get_dummies(df1)

如果需要将新列添加到原始列(如果可能缺少某些组合),请使用^{},方法是使用_拆分列,并使用{a3}创建的所有组合:

^{pr2}$

如果只拆分50k个字符,可以使用原始Python(为了可读性):

>>> a,b,c = zip(*[{0:(1,0,0),1:(0,1,0),2:(0,0,1)}[int(c)] for c in df['genos'][0]])
>>> a,b,c
((0, 0, 0, 0, 0, 0, ...), (1, 1, 1, 1, 0, 1, ...), (0, 0, 0, 0, 1, 0, ...))

相关问题 更多 >