- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我目前正在尝试找到在分类列中对级别进行分组的有效方法,这些级别在 StringType()
的列中出现率较低。我想根据百分比阈值执行此操作,即替换出现在小于 z%
的行中的所有值。此外,重要的是我们可以返回数值(在应用 StringIndexer
之后)和原始值之间的映射。
所以基本上阈值是 25%,这个数据框:
+---+---+---+---+
| x1| x2| x3| x4|
+---+---+---+---+
| a| a| a| a|
| b| b| a| b|
| a| a| a| c|
| b| b| a| d|
| c| a| a| e|
+---+---+---+---+
应该变成这样:
+------+------+------+------+
|x1_new|x2_new|x3_new|x4_new|
+------+------+------+------+
| a| a| a| other|
| b| b| a| other|
| a| a| a| other|
| b| b| a| other|
| other| a| a| other|
+------+------+------+------+
x1
列中的 c
已替换为 other
,所有值均已替换为 other
在 x4
列中,因为它们出现在不到 25%
的行中。
我希望使用常规的 StringIndexer
,并利用值根据其频率排序的事实。我们可以计算要保留多少个值并用例如替换所有其他值-1
。这种方法的问题:这会在 IndexToString
中引发错误,我假设是因为元数据丢失了。
我的问题;有没有好的方法来做到这一点?是否有我可能忽略的内置功能?有没有办法保留元数据?
提前致谢!
df = pd.DataFrame({'x1' : ['a','b','a','b','c'], # a: 0.4, b: 0.4, c: 0.2
'x2' : ['a','b','a','b','a'], # a: 0.6, b: 0.4, c: 0.0
'x3' : ['a','a','a','a','a'], # a: 1.0, b: 0.0, c: 0.0
'x4' : ['a','b','c','d','e']}) # a: 0.2, b: 0.2, c: 0.2, d: 0.2, e: 0.2
df = sqlContext.createDataFrame(df)
最佳答案
我做了一些进一步的调查并偶然发现了 this post关于将元数据添加到 pyspark 中的列。基于此,我能够创建一个名为 group_low_freq
的函数,我认为它非常有效;它仅使用一次 StringIndexer
,然后修改此列和元数据以将所有出现次数少于 x%
的元素放入名为“other”的单独组中。由于我们还修改了元数据,因此我们稍后可以在 IndexToString
上检索字符串。函数和示例如下:
代码:
import findspark
findspark.init()
import pyspark as ps
from pyspark.sql import SQLContext, Column
import pandas as pd
import numpy as np
from pyspark.sql.functions import col, count as sparkcount, when, lit
from pyspark.sql.types import StringType
from pyspark.ml.feature import StringIndexer, IndexToString
from pyspark.ml import Pipeline
import json
try:
sc
except NameError:
sc = ps.SparkContext()
sqlContext = SQLContext(sc)
from pyspark.sql.functions import col
def withMeta(self, alias, meta):
sc = ps.SparkContext._active_spark_context
jmeta = sc._gateway.jvm.org.apache.spark.sql.types.Metadata
return Column(getattr(self._jc, "as")(alias, jmeta.fromJson(json.dumps(meta))))
def group_low_freq(df,inColumns,threshold=.01,group_text='other'):
"""
Index string columns and group all observations that occur in less then a threshold% of the rows in df per column.
:param df: A pyspark.sql.dataframe.DataFrame
:param inColumns: String columns that need to be indexed
:param group_text: String to use as replacement for the observations that need to be grouped.
"""
total = df.count()
for string_col in inColumns:
# Apply string indexer
pipeline = Pipeline(stages=[StringIndexer(inputCol=string_col, outputCol="ix_"+string_col)])
df = pipeline.fit(df).transform(df)
# Calculate the number of unique elements to keep
n_to_keep = df.groupby(string_col).agg((sparkcount(string_col)/total).alias('perc')).filter(col('perc')>threshold).count()
# If elements occur below (threshold * number of rows), replace them with n_to_keep.
this_meta = df.select('ix_' + string_col).schema.fields[0].metadata
if n_to_keep != len(this_meta['ml_attr']['vals']):
this_meta['ml_attr']['vals'] = this_meta['ml_attr']['vals'][0:(n_to_keep+1)]
this_meta['ml_attr']['vals'][n_to_keep] = group_text
df = df.withColumn('ix_'+string_col,when(col('ix_'+string_col)>=n_to_keep,lit(n_to_keep)).otherwise(col('ix_'+string_col)))
# add the new column with correct metadata, remove original.
df = df.withColumn('ix_'+string_col, withMeta(col('ix_'+string_col), "", this_meta))
return df
# SAMPLE DATA -----------------------------------------------------------------
df = pd.DataFrame({'x1' : ['a','b','a','b','c'], # a: 0.4, b: 0.4, c: 0.2
'x2' : ['a','b','a','b','a'], # a: 0.6, b: 0.4, c: 0.0
'x3' : ['a','a','a','a','a'], # a: 1.0, b: 0.0, c: 0.0
'x4' : ['a','b','c','d','e']}) # a: 0.2, b: 0.2, c: 0.2, d: 0.2, e: 0.2
df = sqlContext.createDataFrame(df)
# TEST THE FUNCTION -----------------------------------------------------------
df = group_low_freq(df,df.columns,0.25)
ix_cols = [x for x in df.columns if 'ix_' in x]
for string_col in ix_cols:
idx_to_string = IndexToString(inputCol=string_col, outputCol=string_col[3:]+'grouped')
df = idx_to_string.transform(df)
df.show()
阈值为 25% 的输出(因此每个组必须至少出现在 25% 的行中):
+---+---+---+---+-----+-----+-----+-----+---------+---------+---------+---------+
| x1| x2| x3| x4|ix_x1|ix_x2|ix_x3|ix_x4|x1grouped|x2grouped|x3grouped|x4grouped|
+---+---+---+---+-----+-----+-----+-----+---------+---------+---------+---------+
| a| a| a| a| 0.0| 0.0| 0.0| 0.0| a| a| a| other|
| b| b| a| b| 1.0| 1.0| 0.0| 0.0| b| b| a| other|
| a| a| a| c| 0.0| 0.0| 0.0| 0.0| a| a| a| other|
| b| b| a| d| 1.0| 1.0| 0.0| 0.0| b| b| a| other|
| c| a| a| e| 2.0| 0.0| 0.0| 0.0| other| a| a| other|
+---+---+---+---+-----+-----+-----+-----+---------+---------+---------+---------+
关于python - 如何在 pyspark 的高基数分类列中有效地对具有低频率计数的级别进行分组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48566982/
正如标题所说,我需要制作一个函数,在二进制补码中的 2 个碱基、DEC 和 HEX 之间进行转换。该值使用的位数从一开始就已知。 在深入研究之后,我发现了以下算法: 给定一个 DEC 中的数字。 获取
我的用户文档具有以下格式: { userId: "", userAttributes: [ "", "", ... ""
根据这个: Selectivity is the value between 0 and 1, and it is the fraction of rows returned after applyi
这个词有它 FillChar 是用相同值的字节填充内存补丁的最快方法(不是零,因为有 ZeroMemory),但是是否有等效于用相同的序列填充内存(四字节)整数或基数?像 FillInt 或 Fill
我正在努力寻找建模 1 : 0,1 关系的最佳方法(“可能有一个”或“最多有一个”)。我相信这被称为 Z 基数。 例如,假设我有两个类 Widget和 WidgetTest .并非所有 Widget
我使用parseInt找到了一个片段;它用于获取窗口高度。 这是代码: parseInt($(window).height(), 20); 我很困惑为什么使用 20 作为第二个参数。为什么不是 10
要将十进制数转换为基数 2,我使用: int base2 = 10; Convert.ToString(base2, 2); 输出:1010 但是我怎么能做相反的事情呢?即: 输入:1010输出:10
这是一张真实 table 的再现。假设我有这段代码: CREATE TABLE `testTable` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
由于十六进制(基数 16)使用 0-9A-F,并且(我在这里假设)基数 17 使用 0-9A-G,依此类推。什么符号用过一次0-9A-Z都用完了。 最佳答案 你的问题没有标准答案。 “Base 36”
我正在寻找支持 radix 的浏览器列表Number.toString() 中的参数在 JavaScript 中。全部执行toString ,但我找不到他们是否都支持 radix toString 的
这个问题已经有答案了: What is the radix parameter in Java, and how does it work? (6 个回答) 已关闭 5 年前。 public clas
为什么 (73).toString(36) 返回 21 而 (0.73).toString(36) 返回 0。 qa2voha2volfpsnhmyhqia4i 而不是 0.21? 最佳答案 这是因为
我目前正在研究数据库,我看到 degree 和 cardinality 用作相同的术语,或在某些其他学位定义为否。关系中涉及的实体的数量,并进一步分类为一元、二元和三元。 某些放置度数定义为关系类型的
UML(统一建模语言)中的运算符*和运算符0..*有什么区别? 我看到了这两个基数运算符,但是现在我不必使用哪个基数运算符了。 最佳答案 符号“*”是“0 .. *”的快捷方式。在这种情况下使用的正确
我有位于目录“someApp”中的 Angular 应用程序。网址是 http://example-domain/someApp/#/对于一些带有路径的状态 url 是:http://example-
我想一劳永逸地知道如何编写 UML 基数,因为我经常不得不讨论它们(因此非常欢迎证据和来源:) 如果我想解释一下 Mother可以有几个Child任但是 Child有一个而且只有一个 Mother ,
进行字符算术时,规则是以 10 为基数还是以 8 为基数进行计算?我的书上说'A' = 101(基数为8)或65(基数为10),但是当我将基数为8的字符值插入到我的书给出的关于说明这一点的示例中时,我
该程序是将 4 进制数转换为 2 进制数,并且应该就地完成 #include #include void shiftr(char num[],int i) { memmove(num+i,n
这个问题已经有答案了: JavaScript parseInt is giving me wrong number, what I'm doing wrong? [duplicate] (1 个回答)
我遇到了一个小错误,它似乎表明当您传入图像数据作为其源时,在图像完全加载之前调用了 onload 函数。 这是 HTML 这是 JavaScript: var can
我是一名优秀的程序员,十分优秀!