如何将三列合并为两列,一列是分类的,另一列是数字的? (蟒蛇熊猫)

Posted

技术标签:

【中文标题】如何将三列合并为两列,一列是分类的,另一列是数字的? (蟒蛇熊猫)【英文标题】:How do I merge three columns into two, One categorical and the other numerical? (python pandas) 【发布时间】:2021-10-29 09:17:36 【问题描述】:

这里是数据科学实习生。

好的,我目前在 python 中有一个数据框,如下所示:

        df = pd.DataFrame('Utility': ["Akron", 'Akron', 'Akron', 'Akron'],
                           'Area': ['other', 'other', 'other', 'other'], 
                           'Category': ['Digital', 'Digital', 'Digital', 
                            'Digital'], 
                           'Subcategory': ['Plans', 'Services', 'Asset 
                            Management', 'Billing'], 
                           'Unit':['USD','USD','USD','USD'], 
                           'Value':[0,0,0,0], 
                           "Population Served": 
                           [280000,280000,280000,280000])
print(df)

输出:

      Utility   Area Category       Subcategory Unit  Value  Population Served
0   Akron  other  Digital             Plans  USD      0             280000
1   Akron  other  Digital          Services  USD      0             280000
2   Akron  other  Digital  Asset Management  USD      0             280000
3   Akron  other  Digital           Billing  USD      0             280000

我的主管说她需要能够过滤列单位才能找到 Value 和 Population Served 列。因此,她希望 Unit 列包含两个类别:(Population Served 和 USD),而 Value 列仅包含给定实用程序的人口或支出。注意:我猜她希望所有类别列(区域、类别、子类别等)对于指示给定实用程序服务的人口的任何行都是空白的。

所以我需要它看起来像:

df = pd.DataFrame('Utility': ["Akron", 'Akron', 'Akron', 'Akron', 
                              "Akron", 'Akron', 'Akron', 'Akron'], 
                   'Area': ['other', 'other', 'other', 'other', np.nan, 
                            np.nan, np.nan, np.nan],
                   'Category': ['Digital', 'Digital', 'Digital', 
                   'Digital', np.nan, np.nan, np.nan, np.nan], 
                   'Subcategory': ['Plans', 'Services', 'Asset 
                   Management', 'Billing', np.nan,np.nan,np.nan,np.nan], 
                   'Unit':['USD','USD','USD','USD', 'Pop Served', 'Pop 
                            Served', 'Pop Served', 'Pop Served'], 
                   'Value':[0,0,0,0,280000,280000,280000,280000])

打印(df)

输出:

      Utility   Area Category       Subcategory        Unit   Value
0   Akron  other  Digital             Plans         USD       0
1   Akron  other  Digital          Services         USD       0
2   Akron  other  Digital  Asset Management         USD       0
3   Akron  other  Digital           Billing         USD       0
4   Akron    NaN      NaN               NaN  Pop Served  280000
5   Akron    NaN      NaN               NaN  Pop Served  280000
6   Akron    NaN      NaN               NaN  Pop Served  280000
7   Akron    NaN      NaN               NaN  Pop Served  280000

我一直在尝试使用 pd.melt 来完成此操作,但我不知道如何操作,因为我正在处理将 3 列分成两列的问题。我愿意使用 for 循环执行此操作,但我担心这可能需要很长时间,并且在插入新行时需要精确索引。

需要明确的是,我认为这不是一个好主意。我认为它没有真正的充分理由使文件的大小增加一倍。我也将接受关于如何在 excel 中完成她想要的视图的答案,而无需我玩 csv。

【问题讨论】:

始终以文本形式提供示例数据以及预期的输出,以便人们对其进行处理。 @HenryYik 好的,我编辑了原帖 【参考方案1】:

为了区分不同行中的值,我将源 DataFrame 定义为:

  Utility   Area Category       Subcategory Unit  Value  Population Served
0   Akron  other  Digital             Plans  USD      0             280100
1   Akron  other  Digital          Services  USD     10             280200
2   Akron  other  Digital  Asset Management  USD     20             280300
3   Akron  other  Digital           Billing  USD     30             280400

要获得结果,请运行以下代码:

wrk = df.drop(columns=['Unit']).rename(columns='Value': 'USD')\
    .set_index(df.columns[:4].to_list()).stack().rename('Value')
wrk.index.rename('Unit', level=4, inplace=True)
result = wrk.sort_index(level=4, sort_remaining=False).reset_index()
result.loc[result.Unit == 'Population Served', df.columns[1:4].to_list()] = np.nan

对于我的源数据,结果是:

  Utility   Area Category       Subcategory               Unit   Value
0   Akron  other  Digital             Plans                USD       0
1   Akron  other  Digital          Services                USD      10
2   Akron  other  Digital  Asset Management                USD      20
3   Akron  other  Digital           Billing                USD      30
4   Akron    NaN      NaN               NaN  Population Served  280100
5   Akron    NaN      NaN               NaN  Population Served  280200
6   Akron    NaN      NaN               NaN  Population Served  280300
7   Akron    NaN      NaN               NaN  Population Served  280400

要完全理解上面的代码是如何工作的,运行是逐步的(一种方法 一个接一个)并查看部分结果。

也许您还应该阅读有关所用方法的文档。

编辑

使用 melt 的替代方法:

result = df.drop(columns=['Unit']).rename(columns='Value': 'USD')\
    .melt(id_vars=['Utility', 'Area', 'Category', 'Subcategory'],
        value_vars=['USD', 'Population Served'], var_name='Unit',
        value_name='Value')
result.loc[result.Unit == 'Population Served', df.columns[1:4].to_list()] = np.nan

【讨论】:

嘿@Valdi_Bo 如果我要对 486,000 行重复上述方法,我会用行数替换数字 4 吗? 不是。 “4”不是行数。它是索引级别的编号。而 df.columns[:4] 我曾经避免字面重复源列名。

以上是关于如何将三列合并为两列,一列是分类的,另一列是数字的? (蟒蛇熊猫)的主要内容,如果未能解决你的问题,请参考以下文章

SQL - 插入两列,一列来自表,另一列是常量

如何将excel中的三列数值转换成一列日期

如何将一列中的两列合并为日期与熊猫?

是否可以使表格的前两列与其内容一样宽,而第三列占据剩余空间?

如何合并熊猫数据框中的两列,堆叠在顶部

按两列分组,其中一列是时间戳