преобразовать 132 Тыс. в 132000 и 224,4 Млн в 224 400 000 в pyspark dataframe

#apache-spark #pyspark #pyspark-dataframes

#apache-spark #pyspark

Вопрос:

Я работаю над фреймом данных pyspark, который имеет

 MINFLT  MAJFLT  VSTEXT  VSIZE   RSIZE   VGROW   RGROW
132K    224.4M  11160K  0   224.4M  11160K  0K
134M    224.9K  12260K  0   224.4M  11160K  0K
132K    225.5M  11160K  0   224.4M  11160K  0K  

и пытается получить вывод, подобный:

   MINFLT    MAJFLT  VSTEXT  VSIZE   RSIZE   VGROW   RGROW
  132000   24400000 11160000    0   224400000   11160000 0  

Я попробовал следующий код:

 df.Val = (df.RSIZE.replace(r'[KM] $', '', regex=True).astype(float) * 
      df.RSIZE.str.extract(r'[d.] ([KM] )', expand=False)
      .fillna(1)
      .replace(['K','M'], [10**3, 10**6]).astype(int))
  

Однако я получаю следующую ошибку:

 TypeError                                 Traceback (most recent call last)
<ipython-input-206-489237518a0c> in <module>
----> 1 df.Val = (df.RSIZE.replace(r'[KM] $', '', regex=True).astype(float) * 
      2           df.RSIZE.str.extract(r'[d.] ([KM] )', expand=False)
      3           .fillna(1)
      4           .replace(['K','M'], [10**3, 10**6]).astype(int))

TypeError: 'Column' object is not callable  

Как я могу это исправить?

Ответ №1:

Не могли бы вы дважды проверить, хотите ли вы использовать regexp_replace или ссылаться на replace. Я не нашел замену в классе столбцов. вы могли бы использовать regex_replace, который присутствует в функциональном модуле Pyspark.

У меня есть приведенный ниже код для вашего запроса:

 from pyspark import SparkContext
sc = SparkContext.getOrCreate()


from pyspark.sql import SparkSession
spark = SparkSession(sc)
from pyspark.sql import functions as sf
from pyspark.sql.window import Window
from pyspark.sql.types import *

sample_src = spark.read.csv("sample_src.txt", header=True)
#  use different value for DecimalType, M and K, as per your need
converter = lambda clm, bas_vale: sf.regexp_replace(sf.col(clm),(r'[KM]'),"").cast(DecimalType(20,8)) *bas_vale

sample_src.withColumn("RSIZE", sf.when(sf.col("RSIZE").endswith("M"), converter("RSIZE", 1000000)).otherwise(converter("RSIZE",1000))).show()
  

Ввод:

  ------ ------ ------ ----- ------ ------ ----- 
|MINFLT|MAJFLT|VSTEXT|VSIZE| RSIZE| VGROW|RGROW|
 ------ ------ ------ ----- ------ ------ ----- 
|  132K|224.4M|11160K|    0|224.4M|11160K|   0K|
|  134M|224.9K|12260K|    0|224.4M|11160K|   0K|
|  132K|225.5M|11160K|    0|224.4M|11160K|   0K|
 ------ ------ ------ ----- ------ ------ ----- 
  

Вывод:

  ------ ------ ------ ----- ------------------ ------ ----- 
|MINFLT|MAJFLT|VSTEXT|VSIZE|             RSIZE| VGROW|RGROW|
 ------ ------ ------ ----- ------------------ ------ ----- 
|  132K|224.4M|11160K|    0|224400000.00000000|11160K|   0K|
|  134M|224.9K|12260K|    0|224400000.00000000|11160K|   0K|
|  132K|225.5M|11160K|    0|224400000.00000000|11160K|   0K|
 ------ ------ ------ ----- ------------------ ------ ----- 
  

Ответ №2:

Вы можете использовать карту и выполнить некоторые манипуляции со строками, а затем выполнить окончательный расчет.

 from pyspark.sql.functions import translate, coalesce, lit, substring, expr

df = spark.createDataFrame([
      ('132K', '224.4M', '11160K', '0', '224.4M', '11160K', '0K')
    , ('134M', '224.9K', '12260K', '0', '224.4M', '11160K', '0K')
    , ('132K', '225.5M', '11160K', '0', '224.4M', '11160K', '0K')
], ['MINFLT', 'MAJFLT', 'VSTEXT', 'VSIZE', 'RSIZE', 'VGROW', 'RGROW'])

# create the Map
scale_map = expr("map('K',1000, 'M',1000000, 'G', 1000000000)")

# specify column names you want to process
cols_included = {'MAJFLT', 'RSIZE'}

# define a function to do the conversion
my_convert = lambda c: (translate(c, 'KMG', '')*coalesce(scale_map[substring(c,-1,1)],lit(1))).astype('bigint').alias(c)

df_new = df.select([ my_convert(c) if c in cols_included else c for c in df.columns ])
df_new.show()
 ------ --------- ------ ----- --------- ------ ----- 
|MINFLT|   MAJFLT|VSTEXT|VSIZE|    RSIZE| VGROW|RGROW|
 ------ --------- ------ ----- --------- ------ ----- 
|  132K|224400000|11160K|    0|224400000|11160K|   0K|
|  134M|   224900|12260K|    0|224400000|11160K|   0K|
|  132K|225500000|11160K|    0|224400000|11160K|   0K|
 ------ --------- ------ ----- --------- ------ ----- 
  

Где: в функции my_convert мы используем translate(c, ‘KMG’, «) для удаления символов K M и G (вы можете сделать то же самое с regexp_replace). используйте substring(c,-1,1), чтобы получить последний символ строки и использовать его в качестве ключа для поиска соответствующего значения scale_map[..] . используйте coalesce(.., lit(1)), чтобы установить масштаб 1 , когда такой ключ не найден scale_map .

Комментарии:

1. В этом методе, если у меня есть какой-либо другой столбец, в котором есть строковые значения для (‘apache2′,’mission-contro’,’whoopsie’) — значения в новом фрейме данных превращаются в null, потому что dtypes является строкой

2. проверьте обновленную запись, вам нужно указать столбцы, которые вы хотите включить, а затем использовать if / else в списке-понимание.