字典有时具有多个键

Dictionary sometimes featuring with multiple keys

提问人:Nairda123 提问时间:2/28/2023 更新时间:2/28/2023 访问量:55

问:

我有一个 pandas 数据帧,我想根据字典值创建一个新列。

这是我的 df 和字典:

data = ['One', 'Two', 'Three', 'Four']

df = pd.DataFrame(data, columns=['Count'])

dictionary = {'One':'Red', 'Two':['Red', 'Blue'], 'Three':'Green','Four':['Green','Red', 'Blue']}

这是我想要达到的结果,

enter image description here

最好使用空白字段而不是 None 值,有人知道方法吗?

我尝试了以下方法:

df = df = pd.DataFrame([(k, *v) for k, v in dictionary.items()])
df.columns = ['name'] + [f'n{x}' for x in df.columns[1:]]
df

但是,对于没有多个值的键,它似乎将每个字母的实际字符串拆分到列上,如下所示:enter image description here

将值映射到用分隔符 (,) 分隔的一列的解决方案也很有帮助。

python pandas 字典 lambda 键值

评论


答:

1赞 jezrael 2/28/2023 #1

字典的值中有列表,因此需要通过以下方式防止解包字符串的语句:if-else*

df = pd.DataFrame([(k, *v) 
                   if isinstance(v, list) 
                   else (k, v) for k, v in dictionary.items()])
df.columns = ['name'] + [f'n{x}' for x in df.columns[1:]]
print (df)
    name     n1    n2    n3
0    One    Red  None  None
1    Two    Red  Blue  None
2  Three  Green  None  None
3   Four  Green   Red  Blue

细节

print (((*'Red', )))
('R', 'e', 'd')

print (((*['Red', 'Blue'], )))
('Red', 'Blue')

最好使用空白字段而不是 None 值,有人知道方法吗?

添加 DataFrame.fillna

df = pd.DataFrame([(k, *v) 
                   if isinstance(v, list) 
                   else (k, v) 
                   for k, v in dictionary.items()]).fillna('')
df.columns = ['name'] + [f'n{x}' for x in df.columns[1:]]
print (df)
    name     n1    n2    n3
0    One    Red            
1    Two    Red  Blue      
2  Three  Green            
3   Four  Green   Red  Blue

如果相同的索引和行数使用 DataFrame.join

如果 original 有不同的默认值,则添加到构造函数:df_origRangeIndexindex=df_orig.indexDataFrame

df = pd.DataFrame([(k, *v) 
                   if isinstance(v, list) 
                   else (k, v) 
                   for k, v in dictionary.items()], index=df_orig.index).fillna('')
df.columns = ['name'] + [f'n{x}' for x in df.columns[1:]]

df = df_orig.join(df)

如果需要在 DataFrame.merge 中按列左联接合并:name

df = df_orig.merge(df, on='name', how='left')

评论

0赞 Nairda123 2/28/2023
谢谢,这真的很有帮助,有没有办法将这些值添加为单独的列,但使用主 df 它有许多其他需要保留的列?因为我们刚刚把它作为字典中的新 df
0赞 jezrael 2/28/2023
@Nairda123 - 原始数据帧的行数与此相同?还是需要按原始 DataFrame 按列合并?name
1赞 jezrael 2/28/2023
@Nairda123 - 两种解决方案都添加到答案中。
1赞 mozway 2/28/2023 #2

使用 isinstance 检查是否 a 并确保没有将字符串解压缩为字符:vlist

df = pd.DataFrame([(k, *v) if isinstance(v, list) else (k, v)
                   for k, v in dictionary.items()])
df.columns = ['name'] + [f'n{x}' for x in df.columns[1:]]

输出:

    name     n1    n2    n3
0    One    Red  None  None
1    Two    Red  Blue  None
2  Three  Green  None  None
3   Four  Green   Red  Blue

联接到另一个 DataFrame

使用联接或合并,具体取决于您是要根据索引还是“名称”列进行合并

df2 = pd.DataFrame([(k, *v) if isinstance(v, list) else (k, v)
                   for k, v in dictionary.items()]
                   ).fillna('')
df2.columns = ['name'] + [f'n{x}' for x in df.columns[1:]]

# if same index 
out = df.join(df2)

# Or merging on a common column
out = df.merge(df2, on='name', how='left')

输出:

  original   name     n1    n2    n3
0        A    One    Red            
1        B    Two    Red  Blue      
2        C  Three  Green            
3        D   Four  Green   Red  Blue

使用:df

  original   name
0        A    One       
1        B    Two      
2        C  Three            
3        D   Four

评论

1赞 mozway 2/28/2023
我添加了加入/合并到另一个数据帧所需的代码
0赞 PaulS 2/28/2023 #3

另一个可能的解决方案:

df2 = (pd.DataFrame.from_records([[x, dictionary[x]] for x in dictionary])[1]
       .apply(pd.Series))

df2.columns = [f'Color{x+1}' for x in df2.columns]

pd.concat([df['Count'], df2], axis=1)

输出:

   Count Color1 Color2 Color3
0    One    Red    NaN    NaN
1    Two    Red   Blue    NaN
2  Three  Green    NaN    NaN
3   Four  Green    Red   Blue