【问题标题】:convert columns to rows in pandas based on condition根据条件将列转换为熊猫中的行
【发布时间】:2021-03-03 16:45:35
【问题描述】:

我正在尝试使用 pandas 将列转换为多行。我在数据库中的下表中有数据。下面附上csv格式

CustomerID,Expiry_Date,ProductA,ProductAType,ProductB,ProductBType,ProductC,ProductCType,ProductD,ProductDType,ProductF,ProductFType,ProductG,ProductGType
1,22/11/2020,YES,Trial,NO,Nan,NO,Nan,NO,Nan,YES,Full,NO,Nan
2,30/12/2020,NO,Nan,YES,Full,NO,Nan,NO,Nan,NO,Nan,NO,Nan
3,01/12/2020,NO,Nan,NO,Nan,YES,Full,YES,Trial,NO,Nan,NO,Nan

这是作为数据框的示例数据。

import pandas as pd
import csv
import sys
if sys.version_info[0] < 3: 
    from StringIO import StringIO
else:
    from io import StringIO

TESTDATA = StringIO("""CustomerID,Expiry_Date,ProductA,ProductAType,ProductB,ProductBType,ProductC,ProductCType,ProductD,ProductDType,ProductF,ProductFType,ProductG,ProductGType
1,22/11/2020,YES,Trial,NO,Nan,NO,Nan,NO,Nan,YES,Full,NO,Nan
2,30/12/2020,NO,Nan,YES,Full,NO,Nan,NO,Nan,NO,Nan,NO,Nan
3,01/12/2020,NO,Nan,NO,Nan,YES,Full,YES,Trial,NO,Nan,NO,Nan""")
df=pd.read_csv(TESTDATA, sep=",", quoting=csv.QUOTE_NONE)

该表包含大约 50 列的列表,“是”和“否”选项是客户购买了该产品。

如果客户拥有它及其类型,我需要将行转置为列并输出客户、expiry_id 和带有 Product_name 的 product_column。如下。

CustomerID,Expiry_Date,Product,Type
1,22/11/2020,ProductA,Trial
1,22/11/2020,ProductF,Full
2,30/12/2020,ProductB,Full
3,01/12/2020,ProductC,Full
3,01/12/2020,ProductD,Trial

最后两列也可以是一个连接列

CustomerID,Expiry_Date,Product
1,22/11/2020,ProductA-Trial
1,22/11/2020,ProductF-Full
2,30/12/2020,ProductB-Full
3,01/12/2020,ProductC-Full
3,01/12/2020,ProductD-Trial

知道如何在 pandas 或 sql 中实现这一点吗?

【问题讨论】:

    标签: python sql pandas


    【解决方案1】:

    使用DataFrame.melt 和过滤器YES 值和DataFrame.pop 以供使用并删除boolean indexing 中的列:

    df = df.melt(['CustomerID','Expiry_Date'], var_name='Product')
    df = df[df.pop('value').eq('YES')]
    

    编辑:通过DataFrame.set_index 将第一列转换为MultiIndex 并通过DataFrame.stack 对和取消对列进行整形,然后通过Yes 值过滤Series

    df1 = df.set_index(['CustomerID','Expiry_Date'])
    
    s1 = df1.iloc[:, ::2].stack(dropna=False)
    mask = s1.eq('YES').to_numpy()
    s1 = s1[mask]
    s2 = df1.iloc[:, 1::2].stack(dropna=False)
    s2 = s2[mask]
    

    print (s1)
    CustomerID  Expiry_Date          
    1           22/11/2020   ProductA    YES
                             ProductF    YES
    2           30/12/2020   ProductB    YES
    3           01/12/2020   ProductC    YES
                             ProductD    YES
    dtype: object
    
    print (s2)
    CustomerID  Expiry_Date              
    1           22/11/2020   ProductAType    Trial
                             ProductFType     Full
    2           30/12/2020   ProductBType     Full
    3           01/12/2020   ProductCType     Full
                             ProductDType    Trial
    dtype: object
    

    最后将第三级转换为列并重命名,第二次删除第三级并通过concat连接在一起:

    df1 = s1.reset_index(level=2).rename(columns={'level_2':'Product'})['Product']
    df2 = s2.reset_index(level=2, drop=True).rename('Type')
    
    df = pd.concat([df1, df2], axis=1).reset_index()
    print (df)
    dtype: object
       CustomerID Expiry_Date   Product   Type
    0           1  22/11/2020  ProductA  Trial
    1           1  22/11/2020  ProductF   Full
    2           2  30/12/2020  ProductB   Full
    3           3  01/12/2020  ProductC   Full
    4           3  01/12/2020  ProductD  Trial
    

    最后如果需要加入使用+=DataFrame.pop 删除列:

    df['Product'] += '-' + df.pop('Type') 
    print (df)
       CustomerID Expiry_Date         Product
    0           1  22/11/2020  ProductA-Trial
    1           1  22/11/2020   ProductF-Full
    2           2  30/12/2020   ProductB-Full
    3           3  01/12/2020   ProductC-Full
    4           3  01/12/2020  ProductD-Trial
    

    【讨论】:

    • 我们将如何处理每个产品旁边都有一个产品类型列的输出。例如,每个产品旁边都有一个类型列,如果值为“是”,则该列将是完整或试用。如果“产品”列中的值为“是”,我希望对任何“是”的产品进行完整或试用
    • @Junaid388 - 你能改变数据的样子吗?请不要拍照,这是两次投反对票的原因。
    • 那我该如何分享数据呢? html表格?
    • @Junaid388 - 太棒了,这里的文字最好
    • @Junaid388 - 现在更复杂了,因为已编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2019-12-16
    • 1970-01-01
    • 2017-06-22
    • 1970-01-01
    • 2021-08-08
    相关资源
    最近更新 更多