如何对 pyspark 使用单热编码或 get_dummies 并将列表作为列中的值?
How to use one-hot encoding or get_dummies for pyspark with lists as values in column?
我有一个 spark 数据框:
+-----------+--------------------+
|columnIndex| lists|
+-----------+--------------------+
| 1|[1.0,2.0] |
| 2|[2.0] |
| 3|[1.0] |
| 4|[1.0,3.0] |
+-----------+--------------------+
我需要在one-hot编码后得到以下内容或者get_dummies:
+-----------+--------------------+---+---+---+
|columnIndex| lists|1.0|2.0|3.0|
+-----------+--------------------+---+---+---+
| 1|[1.0,2.0] | 1| 1| 0|
| 2|[2.0] | 0| 1| 0|
| 3|[1.0] | 1| 0| 0|
| 4|[1.0,3.0] | 1| 0| 1|
+-----------+--------------------+---+---+---+
我试过 CountVectorizer(),但无法获得所需的输出。此示例是我拥有的数据的示例。
下面是 one-hot 从一列类别列表中编码的解决方案。
在Pandas
import pandas as pd
data = {'col1': list(range(1,5)), 'lists': [[1.0,2.0], [2.0],[1.0],[1.0,3.0]]}
df = pd.DataFrame.from_dict(data)
df
# Out:
# col1 lists
# 0 1 [1.0, 2.0]
# 1 2 [2.0]
# 2 3 [1.0]
# 3 4 [1.0, 3.0]
s = df['lists'].explode()
df[['col1']].join(pd.crosstab(s.index, s))
# Out:
# col1 1.0 2.0 3.0
# 0 1 1 1 0
# 1 2 0 1 0
# 2 3 1 0 0
# 3 4 1 0 1
在 Pyspark 中
from pyspark.sql import SparkSession
from pyspark.sql.functions import *
spark = SparkSession.builder.getOrCreate()
sparkDF = spark.createDataFrame(df) # spark is the Spark session
sparkDF.show()
# Out:
# +----+----------+
# |col1| lists|
# +----+----------+
# | 1|[1.0, 2.0]|
# | 2| [2.0]|
# | 3| [1.0]|
# | 4|[1.0, 3.0]|
# +----+----------+
sparkDF2 = sparkDF.select(sparkDF.col1,explode(sparkDF.lists).alias('newcol'))
sparkDF2.show()
# Out:
# +----+------+
# |col1|newcol|
# +----+------+
# | 1| 1.0|
# | 1| 2.0|
# | 2| 2.0|
# | 3| 1.0|
# | 4| 1.0|
# | 4| 3.0|
# +----+------+
sparkDF.join(sparkDF2.crosstab('col1', 'newcol').withColumnRenamed('col1_newcol','col1'), 'col1').show()
# Out:
# +----+----------+---+---+---+
# |col1| lists|1.0|2.0|3.0|
# +----+----------+---+---+---+
# | 1|[1.0, 2.0]| 1| 1| 0|
# | 2| [2.0]| 0| 1| 0|
# | 3| [1.0]| 1| 0| 0|
# | 4|[1.0, 3.0]| 1| 0| 1|
# +----+----------+---+---+---+
请注意,这假设列表包含唯一类别,如果列表中重复了一个类别,那么由于 crosstab
.
,它的计数将会出现
例如,如果sparkDF是
+----+---------------+
|col1| lists|
+----+---------------+
| 1| [1.0, 2.0]|
| 2| [2.0]|
| 3| [1.0]|
| 4|[1.0, 3.0, 3.0]|
+----+---------------+
^^^^^^^^^^
那么结果是:
+----+---------------+---+---+---+
|col1| lists|1.0|2.0|3.0|
+----+---------------+---+---+---+
| 1| [1.0, 2.0]| 1| 1| 0|
| 2| [2.0]| 0| 1| 0|
| 3| [1.0]| 1| 0| 0|
| 4|[1.0, 3.0, 3.0]| 1| 0| 2|
+----+---------------+---+---+---+
^^^^
这可以通过简单的转换来调整。
import more_itertools as mit
import numpy as np
import pandas as pd
df = pd.DataFrame({'columnIndex': [1, 2, 3, 4], 'lists': [[1.0, 2.0], [2.0], [1.0], [1.0, 3.0]]})
df = pd.concat([df, pd.DataFrame(columns=[1, 2, 3])])
df[[1, 2, 3]] = [0, 0, 0]
for i in range(0, len(df['lists'])):
index = list(mit.locate([1, 2, 3], lambda x: x in df.loc[i, 'lists']))
index = np.array(index) + 1
df.loc[i, index] = 1
输出
columnIndex lists 1 2 3
0 1.0 [1.0, 2.0] 1 1 0
1 2.0 [2.0] 0 1 0
2 3.0 [1.0] 1 0 0
3 4.0 [1.0, 3.0] 1 0 1
我可以提供基于 pandas 的选项。首先,创建值为 0 的缺失列。此外,基于列号,获得用于设置值的索引。请注意,将 1 添加到索引中。
我有一个 spark 数据框:
+-----------+--------------------+
|columnIndex| lists|
+-----------+--------------------+
| 1|[1.0,2.0] |
| 2|[2.0] |
| 3|[1.0] |
| 4|[1.0,3.0] |
+-----------+--------------------+
我需要在one-hot编码后得到以下内容或者get_dummies:
+-----------+--------------------+---+---+---+
|columnIndex| lists|1.0|2.0|3.0|
+-----------+--------------------+---+---+---+
| 1|[1.0,2.0] | 1| 1| 0|
| 2|[2.0] | 0| 1| 0|
| 3|[1.0] | 1| 0| 0|
| 4|[1.0,3.0] | 1| 0| 1|
+-----------+--------------------+---+---+---+
我试过 CountVectorizer(),但无法获得所需的输出。此示例是我拥有的数据的示例。
下面是 one-hot 从一列类别列表中编码的解决方案。
在Pandas
import pandas as pd
data = {'col1': list(range(1,5)), 'lists': [[1.0,2.0], [2.0],[1.0],[1.0,3.0]]}
df = pd.DataFrame.from_dict(data)
df
# Out:
# col1 lists
# 0 1 [1.0, 2.0]
# 1 2 [2.0]
# 2 3 [1.0]
# 3 4 [1.0, 3.0]
s = df['lists'].explode()
df[['col1']].join(pd.crosstab(s.index, s))
# Out:
# col1 1.0 2.0 3.0
# 0 1 1 1 0
# 1 2 0 1 0
# 2 3 1 0 0
# 3 4 1 0 1
在 Pyspark 中
from pyspark.sql import SparkSession
from pyspark.sql.functions import *
spark = SparkSession.builder.getOrCreate()
sparkDF = spark.createDataFrame(df) # spark is the Spark session
sparkDF.show()
# Out:
# +----+----------+
# |col1| lists|
# +----+----------+
# | 1|[1.0, 2.0]|
# | 2| [2.0]|
# | 3| [1.0]|
# | 4|[1.0, 3.0]|
# +----+----------+
sparkDF2 = sparkDF.select(sparkDF.col1,explode(sparkDF.lists).alias('newcol'))
sparkDF2.show()
# Out:
# +----+------+
# |col1|newcol|
# +----+------+
# | 1| 1.0|
# | 1| 2.0|
# | 2| 2.0|
# | 3| 1.0|
# | 4| 1.0|
# | 4| 3.0|
# +----+------+
sparkDF.join(sparkDF2.crosstab('col1', 'newcol').withColumnRenamed('col1_newcol','col1'), 'col1').show()
# Out:
# +----+----------+---+---+---+
# |col1| lists|1.0|2.0|3.0|
# +----+----------+---+---+---+
# | 1|[1.0, 2.0]| 1| 1| 0|
# | 2| [2.0]| 0| 1| 0|
# | 3| [1.0]| 1| 0| 0|
# | 4|[1.0, 3.0]| 1| 0| 1|
# +----+----------+---+---+---+
请注意,这假设列表包含唯一类别,如果列表中重复了一个类别,那么由于 crosstab
.
例如,如果sparkDF是
+----+---------------+
|col1| lists|
+----+---------------+
| 1| [1.0, 2.0]|
| 2| [2.0]|
| 3| [1.0]|
| 4|[1.0, 3.0, 3.0]|
+----+---------------+
^^^^^^^^^^
那么结果是:
+----+---------------+---+---+---+
|col1| lists|1.0|2.0|3.0|
+----+---------------+---+---+---+
| 1| [1.0, 2.0]| 1| 1| 0|
| 2| [2.0]| 0| 1| 0|
| 3| [1.0]| 1| 0| 0|
| 4|[1.0, 3.0, 3.0]| 1| 0| 2|
+----+---------------+---+---+---+
^^^^
这可以通过简单的转换来调整。
import more_itertools as mit
import numpy as np
import pandas as pd
df = pd.DataFrame({'columnIndex': [1, 2, 3, 4], 'lists': [[1.0, 2.0], [2.0], [1.0], [1.0, 3.0]]})
df = pd.concat([df, pd.DataFrame(columns=[1, 2, 3])])
df[[1, 2, 3]] = [0, 0, 0]
for i in range(0, len(df['lists'])):
index = list(mit.locate([1, 2, 3], lambda x: x in df.loc[i, 'lists']))
index = np.array(index) + 1
df.loc[i, index] = 1
输出
columnIndex lists 1 2 3
0 1.0 [1.0, 2.0] 1 1 0
1 2.0 [2.0] 0 1 0
2 3.0 [1.0] 1 0 0
3 4.0 [1.0, 3.0] 1 0 1
我可以提供基于 pandas 的选项。首先,创建值为 0 的缺失列。此外,基于列号,获得用于设置值的索引。请注意,将 1 添加到索引中。