相当于dplyr点的熊猫

问题描述 投票:1回答:2

对不起,我的解释很繁重,但希望您能理解。

我是R使用者,我发现数据整理中的tidyverse功能非常强大。但是最近我开始学习Python,尤其是熊猫,以扩展我的数据分析机会。本能地,我试图像在使用dplyr时那样去做熊猫。

所以我的问题是,在熊猫中使用方法链接时,是否与dplyr点等效。

这里示例说明了从每个组中大于test_df ['data']中当前值的所有值计算最小值,并且比相同计算但跨新列的最小值计算。

R的示例:

require(dplyr)
require(purrr)
test_df = data.frame(group = rep(c(1,2,3), each = 3),
                     data= c(1:9))
test_df %>%
group_by(group) %>%
mutate(., min_of_max = map_dbl(data, ~data[data > .x] %>% min())) %>%
mutate(., min_of_max_2 = map_dbl(min_of_max, ~min_of_max[min_of_max > .x] %>% min()))

输出:

# A tibble: 9 x 4
# Groups:   group [3]
group  data min_of_max min_of_max_2
<dbl> <int>      <dbl>        <dbl>
1     1     1          2            3
2     1     2          3          Inf
3     1     3        Inf          Inf
4     2     4          5            6
5     2     5          6          Inf
6     2     6        Inf          Inf
7     3     7          8            9
8     3     8          9          Inf
9     3     9        Inf          Inf

我知道dplyr甚至不需要点,但为了更好地理解我的问题的具体含义,我把它放在了句点

在熊猫中做同样的事情

无效示例:

import pandas as pd
import numpy as np
test_df = (
    pd.DataFrame({'A': np.array([1,2,3]*3), 'B': np.array(range(1,10))})
    .sort_values(by = ['A', 'B'])
)
(test_df.assign(min_of_max = test_df.apply(lambda x: (test_df.B[(test_df.B > x.B) &
                                                           (test_df.A[test_df.A == x.A])]).min(), axis = 1))
    .assign(min_of_max2 = 'assume_dot_here'.apply(lambda x: (test_df.min_of_max[(test_df.min_of_max > x.min_of_max) &
                                                           (test_df.A[test_df.A == x.A])]).min(), axis = 1)))

在此示例中,将点放在第二个.assign中将是很好的功能,但在熊猫中不起作用。

有效示例,它破坏了链:

test_df = test_df.assign(min_of_max = test_df.apply(lambda x: 
(test_df.B[(test_df.B > x.B) & (test_df.A[test_df.A == x.A])]).min(), axis = 1))

test_df = test_df.assign(min_of_max2 = test_df.apply(lambda x : 
(test_df.min_of_max[(test_df.min_of_max > x.min_of_max) & (test_df.A[test_df.A 
== x.A])]).min(), axis = 1))

输出:

   A  B  min_of_max  min_of_max2
0  1  1         4.0          7.0
3  1  4         7.0          NaN
6  1  7         NaN          NaN
1  2  2         5.0          8.0
4  2  5         8.0          NaN
7  2  8         NaN          NaN
2  3  3         6.0          9.0
5  3  6         9.0          NaN
8  3  9         NaN          NaN

因此,在第二个.assign中是否有任何便捷的方法可以从链的前一部分调用对象?由于第二秒使用test_df.apply()。赋值将采用初始test_df而不计算test_df['min_of_max']

很抱歉,Python中的代码有些难以理解,我仍在弄清楚如何写得更清晰。

python r pandas
2个回答
1
投票

在Pandas中,运行两个assign调用的链,但是以任何不依赖原始数据帧上下文的方式进行,例如,使用DataFrame.apply调用。下面使用跨索引值的列表理解等效项:

test_df = pd.DataFrame({'group': np.repeat([1,2,3],3), 'data': np.arange(1,10)})

(
   test_df.assign(min_of_max = lambda x: [np.min(x["data"].loc[(x["data"] > x["data"].iloc[i]) &
                                                               (x["group"] == x["group"].iloc[i])]
                                                ) for i in test_df.index.values])
          .assign(min_of_max_2 = lambda x: [np.min(x["min_of_max"].loc[(x["min_of_max"] > x["min_of_max"].iloc[i]) &
                                                                       (x["group"] == x["group"].iloc[i])]
                                                  ) for i in test_df.index.values])
)

#    group  data  min_of_max  min_of_max_2
# 0      1     1         2.0           3.0
# 1      1     2         3.0           NaN
# 2      1     3         NaN           NaN
# 3      2     4         5.0           6.0
# 4      2     5         6.0           NaN
# 5      2     6         NaN           NaN
# 6      3     7         8.0           9.0
# 7      3     8         9.0           NaN
# 8      3     9         NaN           NaN

但是,就像可以在dplyr::mutate中组合分配一样,也可以通过使用DataFrame.assign方法组合DataFrame.assign调用来进行相同的操作(不要与lambda中的lambda混淆)。

R

DataFrame.apply

Pandas

test_df <- data.frame(group = rep(c(1,2,3), each = 3), data = c(1:9))

test_df %>%
  group_by(group) %>%
  mutate(min_of_max = map_dbl(data, ~data[data > .x] %>% min()),
         min_of_max_2 = map_dbl(min_of_max, ~min_of_max[min_of_max > .x] %>% min()))

# # A tibble: 9 x 4
# # Groups:   group [3]
#   group  data min_of_max min_of_max_2
#   <dbl> <int>      <dbl>        <dbl>
# 1     1     1          2            3
# 2     1     2          3          Inf
# 3     1     3        Inf          Inf
# 4     2     4          5            6
# 5     2     5          6          Inf
# 6     2     6        Inf          Inf
# 7     3     7          8            9
# 8     3     8          9          Inf
# 9     3     9        Inf          Inf

顺便说一下,由于熊猫可疑是Wes McKinney在多年前根据R建模的(请参阅test_df = pd.DataFrame({'group': np.repeat([1,2,3],3), 'data': np.arange(1,10)}) test_df.assign(min_of_max = lambda x: [np.min(x["data"].loc[(x["data"] > x["data"].iloc[i]) & (x["group"] == x["group"].iloc[i])] ) for i in test_df.index.values], min_of_max_2 = lambda x: [np.min(x["min_of_max"].loc[(x["min_of_max"] > x["min_of_max"].iloc[i]) & (x["group"] == x["group"].iloc[i])] ) for i in test_df.index.values]) # group data min_of_max min_of_max_2 # 0 1 1 2.0 3.0 # 1 1 2 3.0 NaN # 2 1 3 NaN NaN # 3 2 4 5.0 6.0 # 4 2 5 6.0 NaN # 5 2 6 NaN NaN # 6 3 7 8.0 9.0 # 7 3 8 9.0 NaN # 8 3 9 NaN NaN ),所以基数R倾向于对熊猫更易翻译。下面,paper镜像了withinassign镜像列表理解的用法。

Base R

sapply

0
投票

猜猜我已经找到了使用lambda函数在链的上一部分中引用对象的简要方法。将其传递给带有x参数的assign将把x视为来自链的上一部分的数据帧。

test_df <- within(test_df, {      
  min_of_max <- sapply(1:nrow(test_df), 
                       function(i) min(data[data > data[i] & 
                                            group == group[i]]))

  min_of_max_2 <- sapply(1:nrow(test_df), 
                         function(i) min(min_of_max[min_of_max > min_of_max[i] & 
                                                    group == group[i]]))      
})

test_df[c("group", "data", "min_of_max", "min_of_max_2")]

#   group data min_of_max min_of_max_2
# 1     1    1          2            3
# 2     1    2          3          Inf
# 3     1    3        Inf          Inf
# 4     2    4          5            6
# 5     2    5          6          Inf
# 6     2    6        Inf          Inf
# 7     3    7          8            9
# 8     3    8          9          Inf
# 9     3    9        Inf          Inf

在第二个.assign中传递'lambda y'将把y作为来自链中先前部分的输出

© www.soinside.com 2019 - 2024. All rights reserved.