如何将多个列统一(折叠)为一个分配唯一值

How to unify (collapse) multiple columns into one assigning unique values

提问人:Fakir 提问时间:7/27/2019 最后编辑:Fakir 更新时间:8/1/2019 访问量:260

问:

编辑了我之前的问题:

想要区分连接到特定建筑物的特定电梯(以高度表示)的每个设备(四种类型)。

  1. 由于设备没有唯一的 ID,因此希望通过分组(“BldID”、“BldHt”、“Deivce”)来识别它们并为每个设备分配唯一 ID 以识别任何特定的“设备”。

  2. 计算他们的测试结果,即在几个月的整个持续时间内,在任何特定日期的测试总数 (NG + OK) 中失败 (NG) 的次数 (NG)。

原始数据帧如下所示

BldgID   BldgHt  Device   Date        Time   Result
1074     34.0    790      2018/11/20   10:30  OK
1072     31.0    780      2018/11/19   11:10  NG
1072     36.0    780      2018/11/17   05:30  OK
1074     10.0    790      2018/11/19   06:10  OK   
1074     10.0    790      2018/12/20   11:50  NG
1076     17.0    760      2018/08/15   09:20  NG
1076     17.0    760      2018/09/20   13:40  OK

由于“时间”无关紧要,因此将其删除。想要查找每组每天的 [NG] 数(由 'BldgID'、'BlgHt'、'Device' 组成]。

#aggregate both functions only once by groupby
 df1 = mel_df.groupby(['BldgID','BldgHt','Device','Date'])\
['Result'].agg([('NG', lambda x :(x=='NG').sum()), \
('ALL','count')]).round(2).reset_index()

 #create New_ID by insert with Series with zero fill 3 values
 s = pd.Series(np.arange(1, len(mel_df2) + 1), 
 index=mel_df2.index).astype(str).str.zfill(3)
 mel_df2.insert(0, 'New_ID', s)

现在,筛选后的 DataFrame 如下所示:

 print (mel_df2)
    New_ID  BldgID  BldgHt  Device  Date        NG   ALL
 1   001    1072    31.0    780     2018/11/19   1    2
 8   002    1076    17.0    760     2018/11/20   1    1

如果我分组 ['BldgID', 'BldgHt', 'Device', 'Date'],那么我每天会得到 'NG'。 但它每天都会以不同的方式考虑,如果我分配“唯一”ID,我可以绘制出唯一设备每隔一天的行为方式。

如果我按 ['BldgId', 'BldgHt', 'Device'] 分组,那么我会得到该集(或唯一设备)的整体“NG”,这不是我的目标。

 What I want to achieve is:

 print (mel_df2)

 New_ID  BldgID  BldgHt Device   Date        NG   ALL
 001    1072    31.0    780      2018/11/19   1    2
        1072    31.0    780      2018/12/30   3    4
 002    1076    17.0    760      2018/11/20   1    1
        1076    17.0    760      2018/09/20   2    4 
 003    1072    36.0    780      2018/08/15   1    3

任何提示将不胜感激。

蟒蛇 熊猫

评论

0赞 jezrael 7/28/2019
你能解释更多吗?主要是最后 2 个数字?2018/11/18 2 42018/10/20 2 6
0赞 Fakir 7/28/2019
“ALL”表示完成的测试总数。“NG”表示失败的次数。因此,这 2 6 次意味着 6 次尝试中,2 次失败,其他 4 次“正常”。

答:

2赞 jezrael 7/28/2019 #1

用:

#aggregate both aggregate function only in once groupby
df1 = mel_df.groupby(['BldgID','BldgHt','Device','Date'])\
    ['Result'].agg([('NG', lambda x :(x=='NG').sum()), ('ALL','count')]).round(2).reset_index()

#filter non 0 rows
mel_df2 = df1[df1.NG != 0]

#filter first rows by Date
mel_df2 = mel_df2.drop_duplicates('Date')

#create New_ID by insert with Series with zero fill 3 values
s = pd.Series(np.arange(1, len(mel_df2) + 1), index=mel_df2.index).astype(str).str.zfill(3)
mel_df2.insert(0, 'New_ID', s)

问题数据的输出:

print (mel_df2)
  New_ID  BldgID  BldgHt Device        Date  NG  ALL
1    001    1072    31.0    780  2018/11/19   1    1
8    002    1076    17.0    780  2018/11/20   1    1

评论

0赞 Fakir 7/28/2019
非常感谢。此外,为了统一我以低效的方式所做的两个功能。我想一定有一些有效的方法,但找不到。
0赞 Fakir 7/28/2019
@jezrale 是否可以考虑“BldgID”、“BldgHt”、“Device”进行“New_ID”并计算任何特定日期的“NG”数量?因此,对于相同的“New_ID”,可以计算另一天的“NG”数量。一天内有一次/多次测试。现在,由于日期也包括在内,因此每隔一天具有其他值都是相同的,从而产生一个“New_ID”。希望为“New_ID”分配前 3 个索引。
0赞 jezrael 7/28/2019
@Fakir - 是的,那么需要 GroupBy.ngroup 喜欢更改为pd.Series(np.arange(1, len(mel_df2) + 1), index=mel_df2.index)mel_df.groupby(['BldgID','BldgHt','Device'], sort=False).ngroup().add(1)
0赞 Fakir 7/28/2019
谢谢。为第一个 3 分配一个“New_ID”作为一个组可以像前面的方法一样完成吗?