如何将外观相似的列合并为一个并在熊猫中为其分配名称?

Posted

技术标签:

【中文标题】如何将外观相似的列合并为一个并在熊猫中为其分配名称?【英文标题】:How to collapse similar looking columns into one and assign a name to it in pandas? 【发布时间】:2020-09-12 23:19:51 【问题描述】:

我有一个csv,如下所示

AB22,AD34,GQ22,BQ77a1,BQ77a2,BQ77a3,CA33,LA21,MO22c1,MO22c4
"ab,vd","va,ca","aa","ba,po,la","ma,na,qa","la,oo,aa","ca","na,la","re,te","ka,lo"
"vb,zr","ra,oa","na","oa,yo,sa","xa,ia,ga","lk,po,za","ja","ka,la","rv,gh","xa,jk"

上面的csv 只是我拥有的较大csv 的一个较短版本。它有更多的行和更多的列。但是这个例子对于我的问题来说已经足够了。

现在我有一个看起来像这样的列名列表

columns = ["BQ77", "MO22"]

现在我需要查找 csv 中的列,这些列看起来像我在列表中的每个列名,然后将这些列折叠成一个以逗号分隔的值。

例如对于列BQ77,在csv 中看起来像它的列是BQ77a1,BQ77a2,BQ77a3,对于列MO22,在csv 中的列是MO22c1,MO22c4

现在需要折叠这些列,并且需要将值连接在一起(逗号分隔),并且列名应该是 columns 列表中的列。

所以我的csv 应该是这样的

AB22,AD34,GQ22,BQ77,CA33,LA21,MO22
"ab,vd","va,ca","aa","ba,po,la,ma,na,qa,la,oo,aa","ca","na,la","re,te,ka,lo"
"vb,zr","ra,oa","na","oa,yo,sa,xa,ia,ga,lk,po,za","ja","ka,la","rv,gh,xa,jk"

我创建了列表中给定列与csv 中与它们匹配的列的映射。所以这就是我所做的

import pandas as pd

columns = ["BQ77", "MO22"]
df = pd.read_excel(io="/Users/souvikray/Downloads/test.xlsx", sheet_name="A1") // file originally is an excel file
headers = df.columns.tolist()
col_map = 
for column1 in columns:
    for column2 in headers:
        if column1 in column2:
            if col_map.get(column1):
                col_map[column1].append(column2)
            else:
                col_map[column1] = [column2]

所以我得到一个映射

col_map = "BQ77": ["BQ77a1", "BQ77a2", "BQ77a3"], "MO22": ["MO22c1","MO22c4"]

现在我不确定如何使用这些信息来折叠外观相似的列。我也在网上查到了这个问题Merge multiple column values into one column in python pandas,但这里的列是连续的,但在我的情况下,所需的列出现在某些地方

有什么办法可以做到吗?

注意:由于我没有发布整个 csv,所以要记住的一件事是列值也可能有 int 和 float。

【问题讨论】:

你的理想输出是什么?你能测试一下df.filter(regex='|'.join(columns)).melt() @Datanovice 确定。我已经发布了我的理想输出。寻找So my csv should look like this。我会测试你的建议是否有效 @Datanovice 没有;似乎工作。我没有看到列被折叠。 【参考方案1】:

试试这个,df 是你的主要数据框

A=[["ab,vd","va,ca","aa","ba,po,la","ma,na,qa","la,oo,aa","ca","na,la","re,te","ka,lo"],
   ["vb,zr","ra,oa","na","oa,yo,sa","xa,ia,ga","lk,po,za","ja","ka,la","rv,gh","xa,jk"]]
df=pd.DataFrame(A ,columns = ["AB22","AD34","GQ22","BQ77a1","BQ77a2","BQ77a3","CA33","LA21","MO22c1","MO22c4"])   
columns = ["BQ77", "MO22"]
for c in columns:
    cc = [i for i in df.columns if i.startswith(c)]
    df[c] = df[cc].apply(','.join, axis=1)
    df=df.drop(columns=cc,axis=1)

输出

AB22   AD34 GQ22 CA33   LA21                        BQ77         MO22
0  ab,vd  va,ca   aa   ca  na,la  ba,po,la,ma,na,qa,la,oo,aa  re,te,ka,lo
1  vb,zr  ra,oa   na   ja  ka,la  oa,yo,sa,xa,ia,ga,lk,po,za  rv,gh,xa,jk

【讨论】:

嗨,您的解决方案可能是正确的。但是因为我没有发布整个 csv,所以您不知道这一点。实际上,列值也可能有floatint。所以它会抛出TypeError: ('sequence item 0: expected string, float found', u'occurred at index 0') 的错误。是否可以检查join 仅发生在字符串值的位置。抱歉,我没有把这点说得很清楚。 @SouvikRay 使用df[cc].astype(str).apply(','.join, axis=1) @ShubhamSharma 谢谢。我又往前走了一步。但现在它抛出了UnicodeEncodeError。我想我必须做类似这样的事情***.com/a/52484350/5550284 @ShubhamSharma 我想通了。使用as type('unicode') 不会抛出任何错误。 @SouvikRay 对你有好处。【参考方案2】:

IIUC,使用 join stackfilter

s = df.filter(regex='|'.join(columns)).stack().reset_index()

df1 = df.join(
    s.groupby([s["level_0"], s["level_1"].str[:2]])[0].agg(",".join).unstack(1)
).drop(s["level_1"].unique(), axis=1).rename(columns='BQ' : 'BQ77', 'MO' : 'MO22' )

print(df1)

    AB22   AD34 GQ22 CA33   LA21                        BQ77         MO22
0  ab,vd  va,ca   aa   ca  na,la  ba,po,la,ma,na,qa,la,oo,aa  re,te,ka,lo
1  vb,zr  ra,oa   na   ja  ka,la  oa,yo,sa,xa,ia,ga,lk,po,za  rv,gh,xa,jk

【讨论】:

@Datanvoice 可以修改此代码以处理UnicodeEncodeError 吗?

以上是关于如何将外观相似的列合并为一个并在熊猫中为其分配名称?的主要内容,如果未能解决你的问题,请参考以下文章

如何在大型矩阵中合并具有相似名称的列

SQL:合并表中列的相似值并为其分配标识符

Pandas:合并具有相似名称的列

合并具有不同行的熊猫数据框? [复制]

如何合并/组合熊猫中的列?

熊猫合并如何避免未命名的列