提问人:Nairda123 提问时间:2/28/2023 更新时间:2/28/2023 访问量:55
字典有时具有多个键
Dictionary sometimes featuring with multiple keys
问:
我有一个 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']}
这是我想要达到的结果,
最好使用空白字段而不是 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
但是,对于没有多个值的键,它似乎将每个字母的实际字符串拆分到列上,如下所示:
将值映射到用分隔符 (,) 分隔的一列的解决方案也很有帮助。
答:
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_orig
RangeIndex
index=df_orig.index
DataFrame
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 并确保没有将字符串解压缩为字符:v
list
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
评论