分组和合并行

2024-04-25 21:45:40 发布

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

我有一个大数据帧,看起来像这样:

+----------------------------------------------------------+
| Date           Category        Location       ImpactRate |
+----------------------------------------------------------+
| 2018-04-22     Outage          MT               0.05194  |
| 2018-04-22     Outage          ND               0.02552  |
| 2018-04-22     Outage          SD               0.09962  |
| 2018-04-24     Transport       TX               0.03111  |
+----------------------------------------------------------+

我要做的是创建以下输出:

+-----------------------------------------------------------------------------------+
|   Date           Category        ImpactRate        Break Down             |
+-----------------------------------------------------------------------------------+
| 2018-04-22     Outage          0.17708           MT (29.3%) SD (14.4%) ND (56.3%) |
| 2018-04-24    Transport       0.03111            TX (100.0%)                      |
+-----------------------------------------------------------------------------------+

第一次尝试-GroupBy

grouped_df = df.groupby('Date')['ImpactRate'].apply(list).apply(pd.Series).rename(columns=df['Location'])'

这将创建一个数据帧,其中包含每个位置都不存在的NAN,并创建需要格式化的其他列。你知道吗

第二次尝试-使用itertuples()循环:

r = []
for item in df.itertuples():
    temp_x = df.loc[((df['Category'] == item[2]) & (df['Date'] == item[1]))
    for i in range(temp_x.shape[0]):
        r.append(temp_x['ImpactRate'].iloc[i])

这就产生了一个巨大的冲击率列表——这让我回到原点。你知道吗

我不知道如何解决这个问题。我猜我应该为每个迭代在一个列表中列出一个列表,但我一直在循环。我怎样才能以最具活力的方式实现这个输出呢?(请解释以便我能学习!)你知道吗


Tags: 数据df列表datelocationsditemtemp
2条回答

这是一种使用围绕groupby.transform的矢量化功能的方法。我将Breakdown系列定义为元组列表,因为这是最灵活的格式。如果愿意,可以应用特定的字符串格式。你知道吗

import pandas as pd

df = pd.DataFrame({'Date': ['2018-04-22', '2018-04-22', '2018-04-22', '2018-04-24'],
                   'Category': ['Outage', 'Outage', 'Outage', 'Transport'],
                   'Location': ['MT', 'ND', 'SD', 'TX'],
                   'ImpactRate': [0.05194, 0.02552, 0.09962, 0.03111]})

# apply ratio
df['Total'] = df.groupby(['Date', 'Category'])['ImpactRate'].transform('sum')
df['ImpactRate'] /= df['Total']

# create tuple column
df['Breakdown'] = list(zip(df.Location, df.ImpactRate))

# groupby to list
df = df.groupby(['Category', 'Date', 'Total'])['Breakdown'].apply(list).reset_index()

结果:

print(df)

    Category        Date    Total  \
0     Outage  2018-04-22  0.17708   
1  Transport  2018-04-24  0.03111   

                                           Breakdown  
0  [(MT, 0.293313756494), (ND, 0.144115653942), (...  
1                                        [(TX, 1.0)]  

我觉得不太好。。但是哦,好吧。你知道吗

d = pd.Series(
    df.ImpactRate.values,
    [list(zip(df.Date, df.Category)), df.Location],
    name='Impact Rate'
)

s = d.sum(level=0)
t = d.div(s, level=0).rename('Break Down')

f = lambda t: ' '.join(f'{l} ({v*100:0.2f}%)' for (_, l), v in t.items())

pd.DataFrame(pd.concat(
    [s, t.groupby(level=0).apply(f)], axis=1
).to_dict()).rename_axis(['Date', 'Category']).reset_index()

         Date   Category                           Break Down  Impact Rate
0  2018-04-22     Outage  MT (29.33%) ND (14.41%) SD (56.26%)      0.17708
1  2018-04-24  Transport                         TX (100.00%)      0.03111

相关问题 更多 >