我尝试使用 pyspark.DataFrame
和 pandas.DataFrame
在同一个数据帧 (df) 上执行笛卡尔积。这意味着它是 commuting dataframe。
下面是 pyspark:
>>> a = spark.createDataFrame(data=[(1,'a', '1a'), (2,'b', '2b'),(3,'c', '3c')], schema=['letter', 'number', 'ln'])
>>> b = spark.createDataFrame(data=[(1,'a', '1a'), (2,'b', '2b'),(3,'c', '3c')], schema=['letter', 'number', 'ln'])
>>> a.join(b).show()
+------+------+---+------+------+---+
|letter|number| ln|letter|number| ln|
+------+------+---+------+------+---+
| 1| a| 1a| 1| a| 1a|
| 1| a| 1a| 2| b| 2b|
| 1| a| 1a| 3| c| 3c|
| 2| b| 2b| 1| a| 1a|
| 2| b| 2b| 2| b| 2b|
| 2| b| 2b| 3| c| 3c|
| 3| c| 3c| 1| a| 1a|
| 3| c| 3c| 2| b| 2b|
| 3| c| 3c| 3| c| 3c|
+------+------+---+------+------+---+
为了解释,我在这里做了一个小欺骗。实际上,它们是两个数据框 a
和 b
,但我的问题是应用于一个数据框 a
与它本身。
这里我想删除两种结果:
ln
的行(此处用作 ID)(1,a,1a,2,b,2b)
与 (2,b,2b,1,a,1a)
相同第一条规则可以做如下:
>>> a.join(b, a.nl != b.nl).show(truncate=False)
+------+------+---+------+------+---+
|number|letter|nl |number|letter|nl |
+------+------+---+------+------+---+
|1 |a |1a |2 |b |2b |
|1 |a |1a |3 |c |3c |
|2 |b |2b |1 |a |1a |
|2 |b |2b |3 |c |3c |
|3 |c |3c |1 |a |1a |
|3 |c |3c |2 |b |2b |
+------+------+---+------+------+---+
与交叉连接相同
>>> a.join(a.alias('a1'), a.nl != col('a1.nl'), how='cross').show()
+------+------+---+------+------+---+
|number|letter| nl|number|letter| nl|
+------+------+---+------+------+---+
| 1| a| 1a| 2| b| 2b|
| 1| a| 1a| 3| c| 3c|
| 2| b| 2b| 1| a| 1a|
| 2| b| 2b| 3| c| 3c|
| 3| c| 3c| 1| a| 1a|
| 3| c| 3c| 2| b| 2b|
+------+------+---+------+------+---+
第二条规则应该可以通过 group by
子句实现。但这是一种有效的方法吗?
我尝试使用 itertools.product
但速度很慢,因为我的数据帧有 300 000 行。
下面是熊猫:
使用 pandas 和 NumPy 我尝试创建基于交叉连接的多索引但失败(内存不足)
>>> df1 = pd.DataFrame(data=[(1,'a', '1a'), (2,'b', '2b'),(3,'c', '3c')], columns=['letter', 'number', 'ln'])
>>> df = pd.DataFrame(data=[(1,'a', '1a'), (2,'b', '2b'),(3,'c', '3c')], columns=['letter', 'number', 'ln'])
>>> i1 = df.index
combine_sample = np.transpose([np.tile(i1, len(i1)), np.repeat(i1, len(i1))])
Traceback (most recent call last):
...
numpy.core._exceptions.MemoryError: Unable to allocate 721. GiB for an array with shape (311119, 311119) and data type int64
>>> index= pd.MultiIndex.from_product([df.index,df.index])
Traceback (most recent call last):
...
numpy.core._exceptions.MemoryError: Unable to allocate 361. GiB for an array with shape (96795032161,) and data type int32
预期结果
这是一个像这样的数据帧:
+------+------+---+------+------+---+
|number|letter| nl|number|letter| nl|
+------+------+---+------+------+---+
| 1| a| 1a| 2| b| 2b|
| 1| a| 1a| 3| c| 3c|
| 2| b| 2b| 3| c| 3c|
+------+------+---+------+------+---+
感谢您的见解
答案 0 :(得分:1)
您可以在已排序的数组列上调用删除重复项:
import pyspark.sql.functions as F
result = a.join(b,
F.array(*[a[i] for i in a.columns]) < F.array(*[b[i] for i in b.columns])
)
result.show()
+------+------+---+------+------+---+
|letter|number| ln|letter|number| ln|
+------+------+---+------+------+---+
| 1| a| 1a| 2| b| 2b|
| 1| a| 1a| 3| c| 3c|
| 2| b| 2b| 3| c| 3c|
+------+------+---+------+------+---+