如何用嵌套的for循环和pandas的条件构建列表理解?

时间:2018-10-06 22:08:12

标签: python python-3.x pandas list list-comprehension

我很难使以下复杂的列表理解功能按预期工作。它是带条件的双嵌套for循环。

让我先解释一下我在做什么:

import pandas as pd

dict1 = {'stringA':['ABCDBAABDCBD','BBXB'], 'stringB':['ABDCXXXBDDDD', 'AAAB'], 'num':[42, 13]}

df = pd.DataFrame(dict1)
print(df)
        stringA       stringB  num
0  ABCDBAABDCBD  ABDCXXXBDDDD   42
1          BBXB          AAAB   13

此DataFrame具有两列stringAstringB,它们的字符串包含字符ABCD,{{1 }}。根据定义,这两个字符串的长度相同。

基于这两列,我创建了字典,使X从索引0开始,而stringA从索引stringB开始。

这是我使用的功能:

num

是的。

但是,这些字符串中有'X'字符。这需要一条特殊的规则:如果def create_translation(x): x['translated_dictionary'] = {i: i +x['num'] for i, e in enumerate(x['stringA'])} return x df2 = df.apply(create_translation, axis=1).groupby('stringA')['translated_dictionary'] df2.head() 0 {0: 42, 1: 43, 2: 44, 3: 45, 4: 46, 5: 47, 6: ... 1 {0: 13, 1: 14, 2: 15, 3: 16} Name: translated_dictionary, dtype: object print(df2.head()[0]) {0: 42, 1: 43, 2: 44, 3: 45, 4: 46, 5: 47, 6: 48, 7: 49, 8: 50, 9: 51, 10: 52, 11: 53} print(df2.head()[1]) {0: 13, 1: 14, 2: 15, 3: 16} 位于X中,请不要在字典中创建键/值对。如果stringAX中,则该值不应为stringB,而应为i + x['num']

我尝试了以下列表理解:

-500

那给出了错误的答案。

def try1(x):
    for count, element in enumerate(x['stringB']):
        x['translated_dictionary'] = {i: -500 if element == 'X' else  i + x['num'] for i, e in enumerate(x['stringA']) if e != 'X'}
    return x

没有-500值!

正确的答案是:

df3 = df.apply(try1, axis=1).groupby('stringA')['translated_dictionary']

print(df3.head()[0]) ## this is wrong!
{0: 42, 1: 43, 2: 44, 3: 45, 4: 46, 5: 47, 6: 48, 7: 49, 8: 50, 9: 51, 10: 52, 11: 53}

print(df3.head()[1])   ## this is correct! There is no key for 2:15!
{0: 13, 1: 14, 3: 16}

2 个答案:

答案 0 :(得分:1)

这是一种简单的方法,无需任何理解(因为它们无助于澄清代码):

def create_translation(x):
    out = {}
    num = x['num']
    for i, (a, b) in enumerate(zip(x['stringA'], x['stringB'])):
        if a == 'X':
            pass
        elif b == 'X':
            out[i] = -500
        else:
            out[i] = num
        num += 1
    x['translated_dictionary'] = out
    return x

答案 1 :(得分:0)

为什么不展平df,您可以检查此post并重新创建dict

n=df.stringA.str.len()
newdf=pd.DataFrame({'num':df.num.repeat(n),'stringA':sum(list(map(list,df.stringA)),[]),'stringB':sum(list(map(list,df.stringB)),[])})


newdf=newdf.loc[newdf.stringA!='X'].copy()# remove stringA value X
newdf['value']=newdf.groupby('num').cumcount()+newdf.num # using groupby create the cumcount 
newdf.loc[newdf.stringB=='X','value']=-500# assign -500 when stringB is X
[dict(zip(x.groupby('num').cumcount(),x['value']))for _,x in newdf.groupby('num')] # create the dict for different num by group
Out[390]: 
[{0: 13, 1: 14, 2: 15},
 {0: 42,
  1: 43,
  2: 44,
  3: 45,
  4: -500,
  5: -500,
  6: -500,
  7: 49,
  8: 50,
  9: 51,
  10: 52,
  11: 53}]