[英]python pandas sort within group and apply function
假设我有虹膜数据集。 有没有办法在熊猫中简洁地执行以下操作?
对于那些了解 R 的人,我只想复制以下代码(是的,这是一种解决方法):
iris %>%
group_by(Species) %>%
arrange(desc(Sepal.Length)) %>%
mutate(size_tag = 1,
size_tag = cumsum(size_tag),
size_tag = ifelse(size_tag <= 5, 1, 0))
到目前为止,我有:
from sklearn import datasets
iris = datasets.load_iris()
iris = pd.DataFrame(data= np.c_[iris['data'], iris['target']],
columns= iris['feature_names'] + ['target'])
def fn(group, col_nm):
group[col_nm] = 1
group[col_nm] = np.cumsum(group[col_nm])
group[col_nm] = np.where(group[col_nm] <= 5, 1, 0)
return group
iris['size_tag'] = np.NaN
iris.groupby('target').apply( pd.DataFrame.sort_values, 'sepal length (cm)' ).apply( fn, args = (['size_tag']))
我得到的结果是附加到 DataFrame 的额外行...
我刚刚开始使用 Pandas 和 Python,因此欢迎提出任何意见(例如与编码风格相关的)。
这得到一系列的 1 和 0
iris.sort_values(
'sepal length (cm)', ascending=False
).groupby('target').cumcount().__floordiv__(5).eq(0).astype(np.uint8)
更具可读性
s = iris.sort_values('sepal length (cm)', ascending=False)
c = s.groupby('target').cumcount()
((c // 5) == 0).astype(np.uint8)
使用新列生成副本
s = iris.sort_values('sepal length (cm)', ascending=False)
c = s.groupby('target').cumcount()
top5 = ((c // 5) == 0).astype(np.uint8)
iris.assign(size_tag=top5)
我复制了你的 R 数据框,我认为这做了同样的事情:
iris = iris.sort_values(['target', 'sepal length (cm)'], ascending=False)
iris['size_tag'] = iris.index.isin(iris.groupby('target').head(5).index)*1
我们首先按物种对值进行排序,然后按每个物种组内的萼片长度排序。 然后我们为每个组添加前 5 个标签。
在R
,您不需要cumsum()
来计算行号。 row_number()
函数为您完成:
r$> iris %>%
group_by(Species) %>%
arrange(desc(Sepal.Length)) %>%
mutate(size_tag = if_else(row_number() <= 5, 1, 0))
# A tibble: 150 x 6
# Groups: Species [3]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species size_tag
<dbl> <dbl> <dbl> <dbl> <fct> <dbl>
1 7.9 3.8 6.4 2 virginica 1
2 7.7 3.8 6.7 2.2 virginica 1
3 7.7 2.6 6.9 2.3 virginica 1
4 7.7 2.8 6.7 2 virginica 1
5 7.7 3 6.1 2.3 virginica 1
6 7.6 3 6.6 2.1 virginica 0
7 7.4 2.8 6.1 1.9 virginica 0
8 7.3 2.9 6.3 1.8 virginica 0
9 7.2 3.6 6.1 2.5 virginica 0
10 7.2 3.2 6 1.8 virginica 0
# … with 140 more rows
现在我们有能力在 python 中使用datar
以相同的方式做到这datar
:
>>> from datar.all import f, group_by, arrange, desc, mutate, row_number, if_else
>>> from datar.datasets import iris
>>>
>>> iris >> \
... group_by(f.Species) >> \
... arrange(desc(f.Sepal_Length)) >> \
... mutate(size_tag = if_else(row_number() <= 5, 1, 0))
Sepal_Length Sepal_Width Petal_Length Petal_Width Species size_tag
<float64> <float64> <float64> <float64> <object> <int64>
0 7.9 3.8 6.4 2.0 virginica 1
1 7.7 2.8 6.7 2.0 virginica 1
2 7.7 3.8 6.7 2.2 virginica 1
3 7.7 2.6 6.9 2.3 virginica 1
.. ... ... ... ... ... ...
4 7.7 3.0 6.1 2.3 virginica 1
145 4.5 2.3 1.3 0.3 setosa 0
146 4.4 2.9 1.4 0.2 setosa 0
147 4.4 3.0 1.3 0.2 setosa 0
148 4.4 3.2 1.3 0.2 setosa 0
149 4.3 3.0 1.1 0.1 setosa 0
[Groups: Species (n=3)]
[150 rows x 6 columns]
我是datar
包的作者。 如果您有任何问题,请随时提交问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.