Панды переходят из крайнего левого столбца и изменяют значения по диктанту

#pandas #dataframe #dictionary

Вопрос:

У меня есть следующий словарь и фрейм данных:

 val_dict = {  'key1': ['val1', 'val2', 'val3'],   'key2': ['val4', 'val5'] }  df = pd.DataFrame(data={'val5': [True, False, False],   'val2': [False, True, False],   'val3': [True, True, False],   'val1': [True, False, True],   'val4': [True, True, False],  'val6': [False, False, True]},  index=pd.Series([1, 2, 3], name='index'))  
Указатель val5 val2 val3 val1 val4 val6
1 Правда Ложный Правда Правда Правда Ложный
2 Ложный Правда Правда Ложный Правда Ложный
3 Ложный Ложный Ложный Правда Ложный Правда

Как мне пройти через фрейм данных слева , чтобы, если столбец есть True , другие столбцы в val_dict значениях превратились в False ?

Указатель val5 val2 val3 val1 val4 val6
1 Правда Ложный Правда ложный ложный Ложный
2 Ложный Правда ложный Ложный Правда Ложный
3 Ложный Ложный Ложный Правда Ложный Правда

Например, индекс 1 имеет val5 значение as True , поэтому val4 переключается на False , потому что они оба назначены одному и тому же val_dict ключу. Точно так же есть, val2 False но val3 есть True , поэтому val1 к нему обращаются False . Обратите внимание, что его следует пропустить val6 .

Я попытался преобразовать df в словарь df.to_dict('index') , чтобы работать с двумя словарями. Однако словари неупорядочены, и порядок столбцов важен, поэтому я подумал, что это может привести к ошибкам в коде.

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

1. хотя словари версии 3.6 упорядочены

2. Как бы это было сделано, если бы мы использовали два словаря?

3. Если все значения False для строки, следует ли установить для первого значение True?

4. Если все значения False для строки, строка должна оставаться ложной

Ответ №1:

Один из способов-это комбинация присвоить и замаскировать:

 # either val2 or val3 can be True: com = df.filter(['val2', 'val3']).sum(1).ge(1)   # val2 is the leftmost, so start with that (df.assign(**df.filter(['val1', 'val3']).mask(df.val2, False))  # next is the combination of val2 and val3  .assign(val1 = lambda df: df.val1.mask(com, False),   val4 = lambda df: df.val4.mask(df.val5, False)) ) Out[84]:   val5 val2 val3 val1 val4 val6 index  1 True False True False False False 2 False True False False True False 3 False False False True False True  

Обратите внимание, что val6 не изменен, поэтому значения остаются прежними.

Ответ №2:

Вот что у меня получается при попытке преобразовать в словарь:

 def section_filter(df, section_dict):  result = {}  for index, vals in df.to_dict('index').items():  lst = []  for val in section_dict.values():  lst.append({k:v for k, v in vals.items() if k in val})  for k, v in vals.items():  if k not in [m for mi in section_dict.values() for m in mi]:  lst.append({k: v})  for l in lst:  for i in l:  if l[i]:  l.update({k:False for k in l.keys()})  l[i] = True  break   result[index] = {k: v for d in lst for k, v in d.items()}  return pd.DataFrame.from_dict(result, orient='index', columns=df.columns)  print(df) print() print(section_filter(df, val_dict))   val5 val2 val3 val1 val4 val6 index  1 True False True True True False 2 False True True False True False 3 False False False True False True   val5 val2 val3 val1 val4 val6 1 True False True False False False 2 False True False False True False 3 False False False True False True  

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

1. Насколько это эффективно? Трехуровневый вложенный цикл for-это моя причина для запроса, если только ваши фактические данные не велики

2. Данные довольно малы, но, честно говоря, они очень уродливы и неэффективны. Я пытаюсь масштабировать его, так как на самом деле в фрейме данных намного больше значений, а словарь длиннее