programing

Spark Dataframe은 중복된 이름을 가진 열을 구분합니다.

megabox 2023. 7. 23. 14:10
반응형

Spark Dataframe은 중복된 이름을 가진 열을 구분합니다.

Spark Dataframe에서 알고 있듯이 여러 열에 대해 아래 데이터 프레임 스냅샷에 표시된 것과 같은 이름을 가질 수 있습니다.

[
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})),
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=125231, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0047, 3: 0.0, 4: 0.0043})),
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=145831, f=SparseVector(5, {0: 0.0, 1: 0.2356, 2: 0.0036, 3: 0.0, 4: 0.4132})),
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=147031, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})),
Row(a=107831, f=SparseVector(5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0}), a=149231, f=SparseVector(5, {0: 0.0, 1: 0.0032, 2: 0.2451, 3: 0.0, 4: 0.0042}))
]

위의 결과는 데이터 프레임과의 결합에 의해 생성됩니다. 당신은 다음과 같은 것들이 있음을 수 있습니다.4두 개가 모두 있는 열a그리고.f.

문제는 제가 더 많은 계산을 하려고 할 때 거기에 있습니다.a열, 선택할 수 있는 방법을 찾을 수 없습니다.a해봤어요df[0]그리고.df.select('a')둘 다 오류 메시지 아래로 나를 반환했습니다.

AnalysisException: Reference 'a' is ambiguous, could be: a#1333L, a#1335L.

스파크 API에서 중복된 이름과 열을 다시 구분할 수 있는 방법이 있습니까?아니면 칼럼 이름을 바꿀 수 있는 방법이 있을까요?

몇 가지 데이터부터 시작하겠습니다.

from pyspark.mllib.linalg import SparseVector
from pyspark.sql import Row

df1 = sqlContext.createDataFrame([
    Row(a=107831, f=SparseVector(
        5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})),
    Row(a=125231, f=SparseVector(
        5, {0: 0.0, 1: 0.0, 2: 0.0047, 3: 0.0, 4: 0.0043})),
])

df2 = sqlContext.createDataFrame([
    Row(a=107831, f=SparseVector(
        5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})),
    Row(a=107831, f=SparseVector(
        5, {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0, 4: 0.0})),
])

이 문제에 접근할 수 있는 몇 가지 방법이 있습니다.먼저 상위 열을 사용하여 하위 테이블 열을 명확하게 참조할 수 있습니다.

df1.join(df2, df1['a'] == df2['a']).select(df1['f']).show(2)

##  +--------------------+
##  |                   f|
##  +--------------------+
##  |(5,[0,1,2,3,4],[0...|
##  |(5,[0,1,2,3,4],[0...|
##  +--------------------+

테이블 별칭을 사용할 수도 있습니다.

from pyspark.sql.functions import col

df1_a = df1.alias("df1_a")
df2_a = df2.alias("df2_a")

df1_a.join(df2_a, col('df1_a.a') == col('df2_a.a')).select('df1_a.f').show(2)

##  +--------------------+
##  |                   f|
##  +--------------------+
##  |(5,[0,1,2,3,4],[0...|
##  |(5,[0,1,2,3,4],[0...|
##  +--------------------+

마지막으로 열 이름을 프로그래밍 방식으로 변경할 수 있습니다.

df1_r = df1.select(*(col(x).alias(x + '_df1') for x in df1.columns))
df2_r = df2.select(*(col(x).alias(x + '_df2') for x in df2.columns))

df1_r.join(df2_r, col('a_df1') == col('a_df2')).select(col('f_df1')).show(2)

## +--------------------+
## |               f_df1|
## +--------------------+
## |(5,[0,1,2,3,4],[0...|
## |(5,[0,1,2,3,4],[0...|
## +--------------------+

의 열 이름을 변경하는 것이 좋습니다.join.

df1.select(col("a") as "df1_a", col("f") as "df1_f")
   .join(df2.select(col("a") as "df2_a", col("f") as "df2_f"), col("df1_a" === col("df2_a"))

그 결과DataFrame을 가질 것입니다schema

(df1_a, df1_f, df2_a, df2_f)

다음을 수행하여 가입 중인 모든 열에 대한 별칭을 작성하는 것보다 간단한 방법이 방법은 다음과 같습니다.

df1.join(df2,['a'])

이 기능은 가입 중인 키가 두 테이블에서 동일한 경우에 작동합니다.

https://kb.databricks.com/data/join-two-dataframes-duplicated-columns.html 을 참조하십시오.

이렇게 하면 PySpark에서 동일한 열 이름으로 두 개의 데이터 프레임을 결합할 수 있습니다.

df = df1.join(df2, ['col1','col2','col3'])

네가 한다면.printSchema()그러면 중복된 열이 제거된 것을 볼 수 있습니다.

사용할 수 있습니다.def drop(col: Column)중복된 열을 삭제하는 방법, 예:

DataFrame:df1

+-------+-----+
| a     | f   |
+-------+-----+
|107831 | ... |
|107831 | ... |
+-------+-----+

DataFrame:df2

+-------+-----+
| a     | f   |
+-------+-----+
|107831 | ... |
|107831 | ... |
+-------+-----+

df1을 df2로 가입시키면 데이터 프레임은 다음과 같습니다.

val newDf = df1.join(df2,df1("a")===df2("a"))

DataFrame:newDf

+-------+-----+-------+-----+
| a     | f   | a     | f   |
+-------+-----+-------+-----+
|107831 | ... |107831 | ... |
|107831 | ... |107831 | ... |
+-------+-----+-------+-----+

이제, 우리는def drop(col: Column)다음과 같이 중복된 열 'a' 또는 'f'를 삭제하는 방법:

val newDfWithoutDuplicate = df1.join(df2,df1("a")===df2("a")).drop(df2("a")).drop(df2("f"))

가입하려는 데이터 프레임이 df1 및 df2이고 열 'a'에 가입한다고 가정하면 두 가지 방법이 있습니다.

방법 1

df1.df(df2, 'a', 'left_df')

이것은 놀라운 방법이며 강력하게 추천합니다.

방법 2

df1.df(df2,df1.a == df2.a,'left_df').drop(df2.a)

Spark API를 파고든 후에 처음으로 사용할 수 있다는 것을 알게 되었습니다.alias원래 데이터 프레임에 대한 별칭을 생성하려면 다음을 사용합니다.withColumnRenamed별칭의 모든 열 이름을 수동으로 변경하려면 다음 작업을 수행합니다.join열 이름 중복을 유발하지 않습니다.

자세한 내용은 아래 Spark Dataframe API를 참조하십시오.

pyspark.sql.데이터 프레임.가명을 쓰다

pyspark.sql.데이터 프레임.이름이 변경된 열

하지만, 저는 이것이 단지 골치 아픈 해결책이라고 생각하고, 제 질문에 더 좋은 방법이 없을까 생각합니다.

두 표 모두에서 키 열만 같을 경우 다음 방법을 사용합니다(접근법 1).

left. join(right , 'key', 'inner')

아래가 아닌 (아래 2):

left. join(right , left.key == right.key, 'inner')

접근법 1의 장점:

  • '키'는 최종 데이터 프레임에서 한 번만 표시됩니다.
  • 구문을 사용하기 쉬운

접근법 1 사용의 단점:

  • 키 열에 대한 도움말만 제공
  • 왼쪽 조인의 경우 오른쪽 키 Null 카운트를 사용할 계획이면 작동하지 않는 시나리오입니다.이 경우 위에서 언급한 대로 키 중 하나의 이름을 변경해야 합니다.

이 방법이 최선의 방법은 아닐 수도 있지만, 중복된 열의 이름을 변경하려면(가입 후) 이 작은 함수를 사용하여 이름을 변경할 수 있습니다.

def rename_duplicate_columns(dataframe):
    columns = dataframe.columns
    duplicate_column_indices = list(set([columns.index(col) for col in columns if columns.count(col) == 2]))
    for index in duplicate_column_indices:
        columns[index] = columns[index]+'2'
    dataframe = dataframe.toDF(*columns)
    return dataframe

Glennie Helles Sindholt의 답변에 설명된 것보다 더 복잡한 사용 사례가 있는 경우(예: 다른/소수의 비조인 열 이름이 동일하며 별칭을 사용하는 것이 가장 좋습니다. 예:

df3 = df1.select("a", "b").alias("left")\
   .join(df2.select("a", "b").alias("right"), ["a"])\
   .select("left.a", "left.b", "right.b")

df3.columns
['a', 'b', 'b']

나에게 효과가 있었던 것

import databricks.koalas as ks

df1k = df1.to_koalas()
df2k = df2.to_koalas()
df3k = df1k.merge(df2k, on=['col1', 'col2'])
df3 = df3k.to_spark()

col1과 col2를 제외한 모든 열에는 df1에서 온 경우 "_x"가 추가되고 df2에서 온 경우 "_y"가 추가되어 정확히 제가 필요로 했던 것입니다.

Pyspark 3.2.1 +

32에서 Spark 3..1을 사용하여 .toDF

df.show()
+------+------+---------+
|number|  word|     word|
+------+------+---------+
|     1| apple|   banana|
|     2|cherry|     pear|
|     3| grape|pineapple|
+------+------+---------+

df = df.toDF(*[val + str(i) for i, val in enumerate(df.columns)])

df.show()
+-------+------+---------+
|number0| word1|    word2|
+-------+------+---------+
|      1| apple|   banana|
|      2|cherry|     pear|
|      3| grape|pineapple|
+-------+------+---------+

언급URL : https://stackoverflow.com/questions/33778664/spark-dataframe-distinguish-columns-with-duplicated-name

반응형