您好,我需要帮助清理一些数据。表中的数据包含多个 ID、日期和类别。我对类别 1 和 2、或 1 和 2 和 3、或 1 和 3 的 ID 感兴趣,同时仅保留每个类别具有最大日期的条目。您能否提供此解决方案的最佳脚本?谢谢你!
| ID | 类别 | 日期 | 成本A | 成本B | 成本C | 成本D |
| 1 | 1 | 2016 年 1 月 21 日 | 5000 | 0 | 3000 | 500 |
| 1 | 1 | 2016 年 1 月 21 日 | 1000 | 5000 | 10000 | 0 |
| 1 | 1 | 2016 年 1 月 21 日 | 20000 | 0 | 10 | 50 |
| 1 | 2 | 2016 年 1 月 22 日 | 3000 | 0 | 0 | 50000 |
| 1 | 3 | 2016年2月1日 | 1 | 10 | 900 | 0 |
| 2 | 1 | 2013 年 4 月 2 日 | 0 | 100 | 10000 | 5000 |
| 2 | 2 | 2013 年 4 月 3 日 | 0 | 0 | 0 | 642.49 |
| 2 | 1 | 2013 年 4 月 2 日 | 1 | 10 | 900 | 0 |
| 3 | 2 | 2015 年 3 月 6 日 | 50 | 0 | 0 | 259.58 |
这是一个应该可以工作的小脚本。它找到符合您定义的行。然后将这些行子集到一个新表中。
Names Default To Here( 1 );
dt = Current Data Table();
For Each Row(
If( :date == Col Maximum( :date, :ID ),
currID = :ID;
//currID="1"
cats = Associative Array( dt:category[dt << get rows where( :ID == currID )] ) << get keys;
If( cats[1] == "1" & Length( cats ) > 1,
dt << select rows( Row() )
);
)
);
dtNew = dt << subset( selected columns(0), selected rows(1),
output table("Final")
);
// The above code will allow multiple rows within a given ID, when there are
// multiple rows with the same maximum date. Run the below code to
// get rid of the multiple entries, if that is what is desired
dtNew << select duplicate rows(Match(:ID));
dtNew << delete rows;


如果运行上述脚本的最后 2 行,则会删除重复的 ID 行。

吉姆,
感谢您的帮助。对于任何混乱,我深表歉意。我需要决赛表中必须具有类别 1 和 2 和/或 3 的每个 ID。如果同一类别有重复的 ID,我需要具有最大日期的行。应在此处提供该表。提前谢谢你的帮助。
| ID | 类别 | 日期 | 成本A | 成本B | 成本C | 成本D |
| 1 | 1 | 2016 年 1 月 21 日 | 20000 | 0 | 10 | 50 |
| 1 | 2 | 2016 年 1 月 22 日 | 3000 | 0 | 0 | 50000 |
| 2 | 1 | 2013 年 4 月 2 日 | 0 | 100 | 10000 | 5000 |
| 2 | 2 | 2013 年 4 月 3 日 | 0 | 0 | 0 | 642.49 |
| 3 | 1 | 2015 年 3 月 6 日 | 3000 | 0 | 0 | 第817章 |
| 3 | 2 | 2015 年 3 月 6 日 | 50 | 0 | 0 | 259.58 |
| 4 | 1 | 2015 年 3 月 6 日 | 10000 | 0 | 0 | 710.16 |
| 4 | 2 | 2015 年 3 月 6 日 | 5000 | 0 | 0 | 1087 |
| 4 | 3 | 2015 年 3 月 16 日 | 0 | 0 | 0 | 326.7 |
我上面的例子将类别作为字符列。您的示例是数字。我还更改了逻辑,以确保至少有类别 1&2、1&3 或 1&2&3
Names Default To Here( 1 );
dt = Current Data Table();
For Each Row(
If( :date == Col Maximum( :date, :ID ),
currID = :ID;
cats = Associative Array( dt:category[dt << get rows where( :ID == currID )] ) << get keys;
show(cats);
If( Length( cats ) > 1,
If( cats[1] == 1 & (cats[2] == 2 | cats[2] == 3),
dt << select rows( Row() )
)
);
)
);
dtNew = dt << subset( selected columns( 0 ), selected rows( 1 ), output table( "Final" ) );
您可以使用 Col 函数来实现此目的
Names Default To Here(1);
dt = New Table("Untitled 3",
Add Rows(11),
Compress File When Saved(1),
New Column("ID", Numeric, "Continuous", Format("Best", 12), Set Values([1, 1, 1, 2, 3, 3, 4, 4, 4, 4, 4])),
New Column("Category", Character, "Nominal", Set Values({"A", "A", "B", "A", "A", "C", "A", "A", "B", "B", "C"})),
New Column("Date", Numeric, "Continuous", Format("Best", 12), Set Values([1, 1, 2, 1, 1, 2, 1, 2, 1, 2, 1]))
);
dt << New Column("KEEP", Numeric, Nominal, Formula(
Col Sum(Row() == Col Min(Row(), :category, :id), :id) > 1 & :date == Col Max(:date, :category, :id)
));
将公式更改为 << 选择位置 / << 获取行位置或将其与子集一起使用以获取要保留的行。

编辑:
原始版本没有考虑到类别 1 可能会缺失(假设类别是数字列)
New Column("KEEP", Numeric, Nominal, Formula(
Col Sum(Row() == Col Min(Row(), :category, :id), :id) > 1
& :date == Col Max(:date, :category, :id)
& Col Sum(If(:category == 1, 1, .), :id)
));