【问题标题】:How to deal with dots (.) in column names in SparkR如何处理 SparkR 中列名中的点 (.)
【发布时间】:2016-12-31 16:53:28
【问题描述】:

我正在尝试将本地 csv 文件加载到 SparkR 中,该文件在列名中包含点。阅读文件后,我尝试更改名称并替换为“。”和 ”_”。我仍然无法对创建的 SDF 进行任何操作。 这是可重现的代码:

#writing iris dataset to local
write.csv(iris,"iris.csv",row.names=F)

#reading it back using read.df
iris_sdf<-read.df("iris.csv","csv",header="true",inferSchema="true")

#changing column names
names(iris_sdf)<-c("Sepal_Length","Sepal_Width","Petal_Length","Petal_Width","Species")

#selecting required columna
head(select(iris_sdf,iris_sdf$Sepal_Length,iris_sdf$Sepal_Width))

运行这段代码我收到以下错误:

16/08/24 13:51:24 ERROR RBackendHandler: dfToCols on org.apache.spark.sql.api.r.SQLUtils failed
Error in invokeJava(isStatic = TRUE, className, methodName, ...) : 
  org.apache.spark.sql.AnalysisException: Unable to resolve Sepal.Length given [Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species];
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan$$anonfun$resolve$1$$anonfun$apply$5.apply(LogicalPlan.scala:134)
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan$$anonfun$resolve$1$$anonfun$apply$5.apply(LogicalPlan.scala:134)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan$$anonfun$resolve$1.apply(LogicalPlan.scala:133)
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan$$anonfun$resolve$1.apply(LogicalPlan.scala:129)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
    at scala.collection.Iterator$class.foreach(Iterator.scala:893)
    at scala.collection.AbstractIterator.foreach(Iterator.scala:1336)
    at scala.collection.IterableLike$cl

我应该怎么做才能让它工作?

【问题讨论】:

    标签: r apache-spark apache-spark-sql sparkr


    【解决方案1】:

    当您使用点时,SQL 语法认为您指的是一个表。如果是包含点的列,则需要在名称周围加上反引号

    "`your.column`"
    

    【讨论】:

    • 是的,但是当我已经将所有 'your.column' 替换为 'your_column' - 那么它不应该在后端再次引用 'your.column'。
    • 我认为更改列名的行实际上并没有改变它们。至少,根据堆栈跟踪
    • 看起来是这样......即使我已经使用反引号尝试过你的建议(在列名更改之前)它仍然给出错误 - 选择错误(iris_sdf,Sepal.Width):对象'Sepal.Width' 未找到
    • 您可能必须使用 Spark 从 CSV 中剥离标头,然后在数据帧上应用架构。我没有在 Spark 2.0 中使用 CSV 阅读器玩过太多,不知道如何处理列名中的点
    • @cricket_007 据我所知,提供架构应该足够了,而无需删除标题。
    【解决方案2】:

    这里唯一的解决方法是为阅读器提供架构:

    schema <- structType(
       structField("SepalLength", "double", FALSE),
       structField("SepalWidth",  "double", FALSE),
       structField("PetalLength", "double", FALSE),
       structField("PetalWidth",  "double", FALSE),
       structField("Species",     "string", FALSE))
    
    
    head(read.df("iris.csv", "csv", header="true", schema=schema))
    ##   SepalLength SepalWidth PetalLength PetalWidth Species
    ## 1         5.1        3.5         1.4        0.2  setosa
    ## 2         4.9        3.0         1.4        0.2  setosa
    ## 3         4.7        3.2         1.3        0.2  setosa
    ## 4         4.6        3.1         1.5        0.2  setosa
    ## 5         5.0        3.6         1.4        0.2  setosa
    ## 6         5.4        3.9         1.7        0.4  setosa
    

    【讨论】:

    • 这很有帮助,但是如果我们有 100 列或更多列怎么办?有没有更好的方法来创建模式?
    • 如果您有密码本,您可以通过编程方式创建一个。无论如何,模式推断都很糟糕。
    • 我是 SparkR 的新手,是否可以使用 SparkR?
    • 标准 R 函数应该绰绰有余。
    猜你喜欢
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多