DataFrame挑战:将ID映射到不同行的值.最好带上北极光



考虑这个例子:

import polars as pl
df = pl.DataFrame({
'ID': ['0', '1', '2', '3', '4', '5','6', '7', '8', '9', '10'],
'Name' : ['A','','','','B','','C','','','D', ''], 
'Element' : ['', '4', '4', '0', '', '4', '', '0', '9', '', '6']
})

'Name'链接到'ID'。此ID用作"Element"列中的值。如何将正确的"名称"映射到元素?我还想按'Name' ('Name_list')分组元素,计数它们并按计数值('E_count')排序。

结果df将是:

Name_list Element E_count
-------------------------
'B'       '4'     3
'A'       '0'     2
'C'       '6'     1
'D'       '9'     1

非常感谢反馈;甚至是熊猫的解决方案。

这是北极星的解决方案。我们将使用join来连接IDElement列(经过一些过滤和汇总)。

import polars as pl
(
df.select(["Name", "ID"])
.filter(pl.col("Name") != "")
.join(
df.groupby("Element").agg(pl.count().alias("E_count")),
left_on="ID",
right_on="Element",
how="left",
)
.sort('E_count', reverse=True)
.rename({"Name":"Name_list", "ID":"Element"})
)

注意:这与你的答案中列出的解决方案不同。名称D对应ID9(不是10)

shape: (4, 3)
┌───────────┬─────────┬─────────┐
│ Name_list ┆ Element ┆ E_count │
│ ---       ┆ ---     ┆ ---     │
│ str       ┆ str     ┆ u32     │
╞═══════════╪═════════╪═════════╡
│ B         ┆ 4       ┆ 3       │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ A         ┆ 0       ┆ 2       │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ C         ┆ 6       ┆ 1       │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ D         ┆ 9       ┆ 1       │
└───────────┴─────────┴─────────┘

您也可以使用极值系列。Value_counts方法,它看起来更简洁:

import polars as pl
(
df.select(["Name", "ID"])
.filter(pl.col("Name") != "")
.join(
df.get_column("Element").value_counts(),
left_on="ID",
right_on="Element",
how="left",
)
.sort("counts", reverse=True)
.rename({"Name": "Name_list", "ID": "Element", "counts": "E_count"})
)

如果我正确理解了您的问题,那么您可以使用pandas并执行以下操作:

countdf = pd.merge(df,df[['ID','Name']],left_on='Element',right_on='ID',how='inner')
countdf = pd.DataFrame(countdf.groupby('Name_y')['Element'].count())
result = pd.merge(countdf,df[['Name','ID']],left_on='Name_y',right_on='Name',how='left')
result[['Name','ID','Element']]

using pandas我们可以使用map来映射值,并使用where条件来防止name为空。最后,它是一个分组

df['Name'] = df['Name'].where(cond=df['Element']=="", 
other=df[df['Element']!=""]['Element'].map(lambda x: df[df['ID'] == x]['Name'].tolist()[0]), 
axis=0)
df[df['Element'] != ""].groupby(['Name','Element']).count().reset_index()
Name    Element     ID
0   A   0   2
1   B   4   3
2   C   6   1
3   D   9   1

试试这个,你不需要groupby和join,只需要map和value_counts:

df.drop('Element', axis=1)
.query('Name != "" ')
.assign(E_count = df['ID'].map(df['Element'].value_counts()))

输出:

ID Name  E_count
0  0    A      2.0
4  4    B      3.0
6  6    C      1.0
9  9    D      1.0

最新更新