我很难使以下复杂的列表理解功能按预期工作。它是带条件的双嵌套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具有两列stringA
和stringB
,它们的字符串包含字符A
,B
,C
,D
,{{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
中,请不要在字典中创建键/值对。如果stringA
在X
中,则该值不应为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}
答案 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}]