Pandas Assign,Lambda,List Comprehension Question

z9smfwbn  于 2023-09-29  发布在  其他
关注(0)|答案(3)|浏览(93)

我接收的数据是单列中的dicts列表。每个列表可以有不同的长度。示例数据如下所示:

df = pd.DataFrame(
    [
        [[{'value': 1}, {'value': 2}, {'value': 3}]],
        [[{'value': 4}, {'value': 5}]]
    ],
    columns=['data'],
)

df
                                          data
0   [{'value': 1}, {'value': 2}, {'value': 3}]
1   [{'value': 4}, {'value': 5}]

我想创建一个新列min_val,它包含每行的最小值。我在尝试这个:

df.assign(min_val=lambda row: min(val['value'] for val in row.data))

但我得到了错误:

TypeError: list indices must be integers or slices, not str

一个非常类似的lambda/comprehension组合在Dask Bag中工作,但在原始Pandas中却不起作用,这非常令人困惑。
任何帮助将非常感谢。

wecizke3

wecizke31#

带有可调用参数的assign作用于整个 Dataframe ,而不是行,所以你需要将你的函数applydata系列:

df = df.assign(min_val=df.data.apply(lambda r:min(v['value'] for v in r)))

输出量:

data  min_val
0  [{'value': 1}, {'value': 2}, {'value': 3}]        1
1                [{'value': 4}, {'value': 5}]        4
xxhby3vn

xxhby3vn2#

df['min_val'] = df['data'].apply(lambda x: min(item['value'] for item in x))
bfhwhh0e

bfhwhh0e3#

这是因为你的 listcomp 正在遍历assign返回的新DataFrame的列"data"(* 作为一个整体 *),而不是遍历每个 list/row 的dicts。

# 1st iteration
# `val` is equal to [{'value': 1}, {'value': 2}, {'value': 3}]
# thus, val["value"] (list[str]) will trigger the TypeError

# 2nd iteration
# `val` would be equal to [{'value': 4}, {'value': 5}]]

为了解决这个问题,一个选择是添加另一个循环,这样你就可以到达每个dict的 keys/values

out = df.assign(min_val= [min(k["value"] for k in d) for d in df["data"]])

# 167 µs ± 4.34 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

输出量:

print(out)

                                         data  min_val
0  [{'value': 1}, {'value': 2}, {'value': 3}]        1
1                [{'value': 4}, {'value': 5}]        4

相关问题