Pandas: создание столбца из словаря подмножеств другого столбца

#python #pandas

#python #pandas

Вопрос:

Я работаю с файлами json, которые бывают трех разных видов.

Основное отличие заключается в том, что несколько полей dmaKey и dmaDescription либо существуют вне или внутри словаря одного из столбцов, либо их нет вообще.

Например, этот фрейм данных корректен в своих выходных данных при преобразовании моего файла из json в pandas df.

 file_2 = [{'weekStartDate': '2019-09-02',
  'dmaKey': '803',
  'dmaDescription': 'Los Angeles',
  'scxRequiredFields': {'dmaPopulation': 5476830,
   'systemPopulation': 3810053,
   'strataMarketName': 'Los Angeles'}},
 {'weekStartDate': '2019-09-16',
  'dmaKey': '803',
  'dmaDescription': 'Los Angeles',  
  'scxRequiredFields': {'dmaPopulation': 5476830,
   'systemPopulation': 3810053,
   'strataMarketName': 'Los Angeles'}}]

df2 = pd.DataFrame(file_2)
df2
  

Мои два вопроса заключаются в том, как мне проверить, не существуют ли dmaKey и dmaDescription в той же файловой структуре, что и выше, и если это так, как мне выполнить сопоставление приведенных выше выходных данных и захватить dmaKey и dmaDescription изнутри scxRequiredFields словарного столбца, чтобы создать их собственные столбцы?

 file_1 =[{'weekStartDate': '2020-08-17',
  'scxRequiredFields': {'dmaPopulation': 771210,
   'systemPopulation': 10407,
   'strataMarketName': 'Austin',
   'dmaKey': '635',
   'dmaDescription': 'Austin',
   'eclipseRegionName': 'TEXAS'}},
 {'weekStartDate': '2020-08-10',
  'scxRequiredFields': {'dmaPopulation': 771210,
   'systemPopulation': 10407,
   'strataMarketName': 'Austin',
   'dmaKey': '635',
   'dmaDescription': 'Austin',
   'eclipseRegionName': 'TEXAS'}}]

df1 = pd.DataFrame(file_1)
df1
  

Бывают случаи, когда dmaKey и dmaDescription также полностью отсутствуют, так что это третий случай, который мне нужно было бы учесть.

 file_3 =[{'weekStartDate': '2020-09-17',
  'scxRequiredFields': {'dmaPopulation': 7712105432,
   'systemPopulation': 10407123,
   'strataMarketName': 'Austin',
   'eclipseRegionName': 'TEXAS'}},
 {'weekStartDate': '2020-09-10',
  'scxRequiredFields': {'dmaPopulation': 7712101234,
   'systemPopulation': 10407123,
   'strataMarketName': 'Austin',
   'eclipseRegionName': 'TEXAS'}}]

df3 = pd.DataFrame(file_3)
df3
  

Ответ №1:

Я бы счел это вопросом манипулирования данными, прежде чем создавать из них dataframe. Вот некоторый код для выполнения именно этого:

 def populateValues( json_file, keys ):
  for row in json_file:
    for k in ('dmaKey','dmaDescription'):
      if k not in row:
        if 'scxRequiredFields' in row:
          row[k] = row['scxRequiredFields'].get( k , defaults(row,k) )
        else:
          row[k] = defaults(row,k)
  

Вот как вы могли бы вызвать этот метод (ну, в любом случае, это мой тестовый код):

 keys = ('dmaKey','dmaDescription')
for test in ( file_2, file_3, file_1 ):
  populateValues( test, keys )
  json.dump( test, sys.stdout, indent = 2 )
  print()
  print()
  

Результатом вызова populateValues() является то, что структура данных test обрабатывается таким образом, что все недостающие ключи заполняются в словаре верхнего уровня.

Вы не указали, что делать, если значение полностью отсутствует в словаре или в подразделе ‘sceRequiredFields’. Вместо этого я просто вызвал функцию, вызываемую defaults(row,k) так, чтобы функция могла указать значение по умолчанию для данного ключа k в зависимости от чего-либо в строке. Вот тривиальная функция, которая просто объединяет имя ключа с «Default»:

 def defaults( r, k ) :
  return f"Default: {k}"
  

Вот результат тестового цикла (я добавил несколько комментариев, чтобы вы могли видеть разные результаты входного файла):

 # file_2 - no fixes required
[
  {
    "weekStartDate": "2019-09-02",
    "dmaKey": "803",
    "dmaDescription": "Los Angeles",
    "scxRequiredFields": {
      "dmaPopulation": 5476830,
      "systemPopulation": 3810053,
      "strataMarketName": "Los Angeles"
    }
  },
  {
    "weekStartDate": "2019-09-16",
    "dmaKey": "803",
    "dmaDescription": "Los Angeles",
    "scxRequiredFields": {
      "dmaPopulation": 5476830,
      "systemPopulation": 3810053,
      "strataMarketName": "Los Angeles"
    }
  }
]

# file_3 - only dumb default values get inserted
[
  {
    "weekStartDate": "2020-09-17",
    "scxRequiredFields": {
      "dmaPopulation": 7712105432,
      "systemPopulation": 10407123,
      "strataMarketName": "Austin",
      "eclipseRegionName": "TEXAS"
    },
    "dmaKey": "Default: dmaKey",
    "dmaDescription": "Default: dmaDescription"
  },
  {
    "weekStartDate": "2020-09-10",
    "scxRequiredFields": {
      "dmaPopulation": 7712101234,
      "systemPopulation": 10407123,
      "strataMarketName": "Austin",
      "eclipseRegionName": "TEXAS"
    },
    "dmaKey": "Default: dmaKey",
    "dmaDescription": "Default: dmaDescription"
  }
]

# file_1 - Values are taken from scxRequiredFields
[
  {
    "weekStartDate": "2020-08-17",
    "scxRequiredFields": {
      "dmaPopulation": 771210,
      "systemPopulation": 10407,
      "strataMarketName": "Austin",
      "dmaKey": "635",
      "dmaDescription": "Austin",
      "eclipseRegionName": "TEXAS"
    },
    "dmaKey": "635",
    "dmaDescription": "Austin"
  },
  {
    "weekStartDate": "2020-08-10",
    "scxRequiredFields": {
      "dmaPopulation": 771210,
      "systemPopulation": 10407,
      "strataMarketName": "Austin",
      "dmaKey": "635",
      "dmaDescription": "Austin",
      "eclipseRegionName": "TEXAS"
    },
    "dmaKey": "635",
    "dmaDescription": "Austin"
  }
]