Python Pandas - Appending/updating 带有字典列的数据框中的键值对
Python Pandas - Appending/updating key value pairs inside a dataframe with a dict column
有这个数据框
d = {'objects':[{'Sand':10},{'Seawater': 2, 'Crab': 30},{'Parasol': 50}]}
df = pd.DataFrame(data=d)
我想要这个键值对
{'Small': 1000}
插入到至少有一个值小于 40 的键值对的每一行。
objects
0 {'Sand': 10, 'Small': 1000}
1 {'Seawater': 2, 'Crab': 30, 'Small': 1000}
2 {'Parasol': 50}
我试过遍历它,但结果是 'None'。
def your_small(x):
if any(value < 40 for value in x.values()):
return x.update({'Small': 1000})
d = {'objects':[{'Sand':10},{'Seawater': 2, 'Crab': 30},{'Parasol': 50}]}
df = pd.DataFrame(data=d)
df['objects'] = df['objects'].map(your_small)
objects
0 None
1 None
2 None
正如@ALoll 所说,您可能需要重新考虑您的方法。
如果您想让现有代码正常工作,您必须考虑 map 的工作原理:您必须 return map 函数中的一个值。 x.update
returns None
,如果您的条件不满足,您必须 return x 原样:
def your_small(x):
if any(value < 40 for value in x.values()):
return {**x, 'Small': 1000}
return x
如果不是真的需要听写,这里有一个使用 MultiIndex 的方法。在这里,我假设单独的字典大多具有不重叠的键,因此长 DataFrame 似乎更合适。 (如果大多数字典有重叠的键,一个宽的 DataFrame 可能会更好)
import pandas as pd
df = pd.concat([pd.DataFrame.from_dict(di, orient='index', columns=['N']) for di in d['objects']],
keys=range(len(d['objects'])))
# N
#0 Sand 10
#1 Seawater 2
# Crab 30
#2 Parasol 50
# Determine which original "rows" have at least one value < 40
s = df.N.lt(40).groupby(level=0).any()
df_add = pd.DataFrame({'N': 1000},
index = pd.MultiIndex.from_product([s[s].index, ['Small']]))
# Join them:
df = pd.concat([df, df_add]).sort_index()
# N
#0 Sand 10
# Small 1000
#1 Crab 30
# Seawater 2
# Small 1000
#2 Parasol 50
这是一个具有宽 DataFrame 的版本。更容易操作,但会变得非常大。
df = pd.DataFrame.from_records(d['objects'])
# Sand Seawater Crab Parasol
#0 10.0 NaN NaN NaN
#1 NaN 2.0 30.0 NaN
#2 NaN NaN NaN 50.0
df.loc[df.lt(40).any(1), 'Small'] = 1000
# Sand Seawater Crab Parasol Small
#0 10.0 NaN NaN NaN 1000.0
#1 NaN 2.0 30.0 NaN 1000.0
#2 NaN NaN NaN 50.0 NaN
有这个数据框
d = {'objects':[{'Sand':10},{'Seawater': 2, 'Crab': 30},{'Parasol': 50}]}
df = pd.DataFrame(data=d)
我想要这个键值对
{'Small': 1000}
插入到至少有一个值小于 40 的键值对的每一行。
objects
0 {'Sand': 10, 'Small': 1000}
1 {'Seawater': 2, 'Crab': 30, 'Small': 1000}
2 {'Parasol': 50}
我试过遍历它,但结果是 'None'。
def your_small(x):
if any(value < 40 for value in x.values()):
return x.update({'Small': 1000})
d = {'objects':[{'Sand':10},{'Seawater': 2, 'Crab': 30},{'Parasol': 50}]}
df = pd.DataFrame(data=d)
df['objects'] = df['objects'].map(your_small)
objects
0 None
1 None
2 None
正如@ALoll 所说,您可能需要重新考虑您的方法。
如果您想让现有代码正常工作,您必须考虑 map 的工作原理:您必须 return map 函数中的一个值。 x.update
returns None
,如果您的条件不满足,您必须 return x 原样:
def your_small(x):
if any(value < 40 for value in x.values()):
return {**x, 'Small': 1000}
return x
如果不是真的需要听写,这里有一个使用 MultiIndex 的方法。在这里,我假设单独的字典大多具有不重叠的键,因此长 DataFrame 似乎更合适。 (如果大多数字典有重叠的键,一个宽的 DataFrame 可能会更好)
import pandas as pd
df = pd.concat([pd.DataFrame.from_dict(di, orient='index', columns=['N']) for di in d['objects']],
keys=range(len(d['objects'])))
# N
#0 Sand 10
#1 Seawater 2
# Crab 30
#2 Parasol 50
# Determine which original "rows" have at least one value < 40
s = df.N.lt(40).groupby(level=0).any()
df_add = pd.DataFrame({'N': 1000},
index = pd.MultiIndex.from_product([s[s].index, ['Small']]))
# Join them:
df = pd.concat([df, df_add]).sort_index()
# N
#0 Sand 10
# Small 1000
#1 Crab 30
# Seawater 2
# Small 1000
#2 Parasol 50
这是一个具有宽 DataFrame 的版本。更容易操作,但会变得非常大。
df = pd.DataFrame.from_records(d['objects'])
# Sand Seawater Crab Parasol
#0 10.0 NaN NaN NaN
#1 NaN 2.0 30.0 NaN
#2 NaN NaN NaN 50.0
df.loc[df.lt(40).any(1), 'Small'] = 1000
# Sand Seawater Crab Parasol Small
#0 10.0 NaN NaN NaN 1000.0
#1 NaN 2.0 30.0 NaN 1000.0
#2 NaN NaN NaN 50.0 NaN