我有一个 .csv 文件(大小约为 400MB),其中包含 700K 行结构化数据。表结构为:
+----+----------+-------+-----------+--------+--------+
| Id | Category | List1 | List2 | Value1 | Value2 |
+----+----------+-------+-----------+--------+--------+
| 1 | 1 | A,B,C | Cat1,Cat2 | 100 | 5 |
| 2 | 1 | D,F | Cat1,Cat4 | 120 | 4 |
| 3 | 2 | E,A | Cat3 | 140 | 2 |
| 4 | 2 | E,A | NULL | 110 | 3 |
| 5 | 3 | B | Cat2 | 100 | 6 |
+----+----------+-------+-----------+--------+--------+
对于我要计算的表的每一行 (CurrentRow):
CurrentRow.Value3 = SUM(Value1)/SUM(Value2) 表中满足以下条件的所有其他行 (OtherRow):
Condition1 = CurrentRow.Category != OtherRow.Category
Condition2 = CurrentRow.List1 intersects OtherRow.List1
Condition3 = CurrentRow.List2 intersects OtherRow.List2 or CurrentRow.List2 = NULL or OtherRow.List2 = NULL
另外,我想列出计算 Value3 所涉及的行的 ID。
第一行的示例:
Condition1:第一行的类别值为 1。因此,第 3-4 行满足条件 #1,因为它们的类别值不等于 1。
Condition2:列“List1”的值为“A,B,C " 与值“E,A”(第 3 行)、“E,A”(第 4 行)、“B”(第 5 行)相交。
条件3:列“List2”的值“Cat1,Cat2”与值“Cat1,Cat4”(第 2 行)、“Cat2”(第 5 行)相交,并且我们采用第 4 行,因为它具有“NULL”值.
因此,我们选择第 4 行和第 5 行,因为它们都满足所有条件。
值 3 = (110+100)/(3+6) = 210/9 = 23.33
Ids = "4,5"
上表的结果将是:
+----+----------+-------+-----------+--------+--------+--------+------+
| Id | Category | List1 | List2 | Value1 | Value2 | Value3 | Ids |
+----+----------+-------+-----------+--------+--------+--------+------+
| 1 | 1 | A,B,C | Cat1,Cat2 | 100 | 5 | 23.33 | 4,5 |
| 2 | 1 | D,F | Cat1,Cat4 | 120 | 4 | NULL | NULL |
| 3 | 2 | E,A | Cat3 | 140 | 2 | NULL | NULL |
| 4 | 2 | E,A | NULL | 110 | 3 | 20 | 1 |
| 5 | 3 | B | Cat2 | 100 | 6 | 20 | 1 |
+----+----------+-------+-----------+--------+--------+--------+------+
我曾尝试在 python 中使用 pandas 来做到这一点:
data = pd.read_pickle('data.df')
for _index, _record in data.iterrows():
category = _record["Category"]
list1 = _record["List1"]
list2 = _record["list2"]
candidates = data.loc[(data['Category'] != category) & (pd.Series(list1).isin(data["List1"]).any()) & ((pd.Series(list2).isin(data["List2"]).any()) | (data["List2"][0] == 'NULL') | (list2[0] == 'NULL'))]
value1_sum = candidates["Value1"].sum()
value2_sum = candidates["Value2"].sum()
ids = candidates[['Id']].to_numpy()
if value2_sum > 0:
data.loc[_index, "Value3"] = value1_sum/ value2_sum
data.loc[_index, "Ids"] = ids
data.to_csv('result.csv')
它适用于少量行,但需要永远处理 700K 行。有什么方法可以优化这个算法吗?