pandas DataFrame的transform与applymap有什么区别

dar*_*cyq 1 python dataframe pandas

虽然applymapDataFrame上的函数在元素方面运行,但该transform函数似乎实现了相同的功能,除了声称返回类似索引的DataFrame.

问题:

  1. 是否存在其中一个工作而另一个不工作的用例?
  2. 一个人的表现比另一个人好吗?
  3. 文档中陈述了什么类似索引的DataFrame?

piR*_*red 9

不同的用例.当比较他们,这是非常有用的培养applyagg为好.

建立

np.random.seed([3,1415])
df = pd.DataFrame(np.random.randint(10, size=(6, 4)), columns=list('ABCD'))

df

   A  B  C  D
0  0  2  7  3
1  8  7  0  6
2  8  6  0  2
3  0  4  9  7
4  3  2  4  3
5  3  6  7  7
Run Code Online (Sandbox Code Playgroud)

pd.DataFrame.applymap
这将获取一个函数并返回一个新的数据帧,该函数的结果将应用于每个单元格中的值,并用结果替换单元格的值.

df.applymap(lambda x: str(x) * x)

          A        B          C        D
0                 22    7777777      333
1  88888888  7777777              666666
2  88888888   666666                  22
3               4444  999999999  7777777
4       333       22       4444      333
5       333   666666    7777777  7777777
Run Code Online (Sandbox Code Playgroud)

pd.DataFrame.agg
采用一个或多个功能.每个函数都应该是一个聚合函数.这意味着每个函数都应用于每个列,并且应该返回一个替换整个列的值.例子是'mean''max'.这两个都采用一组数据并返回一个标量.

df.agg('mean')

A    3.666667
B    4.500000
C    4.500000
D    4.666667
dtype: float64
Run Code Online (Sandbox Code Playgroud)

要么

df.agg(['mean', 'std', 'first', 'min'])

             A         B         C         D
mean  3.666667  4.500000  4.500000  4.666667
std   3.614784  2.167948  3.834058  2.250926
min   0.000000  2.000000  0.000000  2.000000
Run Code Online (Sandbox Code Playgroud)

pd.DataFrame.transform
使用一个预期应用于列的函数并返回相同大小的列.

df.transform(lambda x: x / x.std())

          A         B         C         D
0  0.000000  0.922531  1.825742  1.332785
1  2.213133  3.228859  0.000000  2.665570
2  2.213133  2.767594  0.000000  0.888523
3  0.000000  1.845062  2.347382  3.109832
4  0.829925  0.922531  1.043281  1.332785
5  0.829925  2.767594  1.825742  3.109832
Run Code Online (Sandbox Code Playgroud)

pd.DataFrame.apply
pandas试图弄清楚是否apply正在减少它正在运行的列的维度(也称为聚合),或者它是否正在将列转换为相同大小的另一列.当它计算出来时,它会运行剩余的操作,就像它是聚合或转换过程一样.

df.apply('mean')

A    3.666667
B    4.500000
C    4.500000
D    4.666667
dtype: float64
Run Code Online (Sandbox Code Playgroud)

要么

df.apply(lambda x: (x - x.mean()) / x.std())

          A         B         C         D
0 -1.014353 -1.153164  0.652051 -0.740436
1  1.198781  1.153164 -1.173691  0.592349
2  1.198781  0.691898 -1.173691 -1.184698
3 -1.014353 -0.230633  1.173691  1.036611
4 -0.184428 -1.153164 -0.130410 -0.740436
5 -0.184428  0.691898  0.652051  1.036611
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,但你没有回答我的问题 (4认同)
  • @darcyq你真的需要知道如何编写源代码来理解函数的不同之处吗?这个答案完美地解释了这两个功能如何工作.一个在一个系列上工作,另一个在单个细胞上工作.如果你必须真正看到源代码,它可以在GitHub免费获得,所以[自己敲出](https://github.com/pandas-dev/pandas/blob/master/pandas/core/frame.py#L4792) . (4认同)
  • @darcyq这位用户花了很多时间回答你的问题.事实上,你的问题应该过于宽泛.你所有问题的答案显然是_it depends_.它取决于数据,它取决于上下文,版本,您的系统,_everything_.你不能指望对这类问题采取一刀切的答案.最重要的是,你贬低了这个答案.为什么要这么做? (2认同)

A. *_*jar 6

.transform()返回文档中所述的类似索引的 DataFrame是什么意思?

这意味着.transform()将一个函数应用于 DataFrame 中的每个值(或一个组,一旦前面带有groupby),并返回另一个与输入长度相同的 DataFrame,因此要强调:它将输入索引标签保留在输出中。

是否存在 applymap/transform 之一而另一个没有的用例?

当然。这里有些例子:

1) applymap VS 变换

由于applymap对 DataFrame 的所有元素执行,因此不能applymap对 Series 执行:

df['Quantity'].transform(lambda x: x+10) # successful
df['Quantity'].apply(lambda x: x+10) # successful
df['Quantity'].applymap(lambda x: x+10) # gives AttributeError: 'Series' object has no attribute 'applymap'

# unless you cast it to DataFrame:
pd.DataFrame(df['Quantity']).applymap(lambda x: x+10) # successful
Run Code Online (Sandbox Code Playgroud)

另一个重要的区别是,尽管.applymap()它按元素进行操作,但.transform()可以执行按组操作,这将在下一部分中提到。

此外,applymap前面不能带有groupby

2)应用Vs变换

applytransform只要您在 DataFrame 列上执行它们,它们就可以互换。这是一个简单的例子:

# imagine the following DataFrame
df = pd.DataFrame({'Label': ['A', 'B', 'C', 'A', 'C'],
                   'Values': [0,1,2,3,4],
                   'Quantity': [5,6,7,8,9]}, index = list('VWXYZ'))


    Label   Quantity   Values
---------------------------------
V    A         5         0
W    B         6         1
X    C         7         2
Y    A         8         3
Z    C         9         4


df.loc[:, ['Quantity', 'Values']].apply(lambda x: x+10)
df.loc[:, ['Quantity', 'Values']].transform(lambda x: x+10)
# both of them give the following same result:

    Quantity   Values
-------------------------
V    15          10
W    16          11
X    17          12
Y    18          13
Z    19          14
Run Code Online (Sandbox Code Playgroud)

一旦他们接受手术,主要的区别就会显现出来groupby。例如:

label_grouping = df.groupby('Label')
label_grouping.apply(lambda x: x.mean())
# output:

      Quantity   Values
Label
-----------------------
A       6.5       1.5
B       6.0       1.0
C       8.0       3.0

label_grouping.transform(lambda x: x.mean())
# see how `transform` could manage to keeps the input index labels in the output
# output:

    Quantity   Values
------------------------
V     6.5       1.5
W     6.0       1.0
X     8.0       3.0
Y     6.5       1.5
Z     8.0       3.0
Run Code Online (Sandbox Code Playgroud)

上面的例子清楚地展示了如何transform保留输入DataFrame索引;因此,为了更好地利用这一独有功能,下面的简短示例试图transform通过计算每个产品所代表的订单总数的百分比来阐明如何从操作的输入和输出之间的索引对齐中受益:

df_sales = pd.DataFrame({'OrderID': [1001,1001,1001,1002,1002],
                         'Product': ['p1','p2','p3','p1','p4'],
                         'Quantity': [30,20,70,160,40]})


    OrderID   Product   Quantity
-----------------------------------
0    1001       p1        30
1    1001       p2        20
2    1001       p3        70
3    1002       p1        160
4    1002       p4        40


df_sales['total_per_order'] = df_sales.groupby(['OrderID'])['Quantity'].transform(lambda x: x.sum()) 
df_sales['pct_of_order'] = df_sales['Quantity'] / df_sales['total_per_order']


    OrderID   Product   Quantity   total_per_order   pct_of_order
----------------------------------------------------------------------
0    1001       p1        30           120             0.250000
1    1001       p2        20           120             0.166667
2    1001       p3        70           120             0.583333
3    1002       p1        160          200             0.800000
4    1002       p4        40           200             0.200000
Run Code Online (Sandbox Code Playgroud)

强烈建议点击此链接获取更详细的示例:https ://pbpython.com/pandas_transform.html

许多聚合函数直接内置于groupby对象中,以节省您的打字时间。具体来说,可以受益的一些常见的有(前缀为 gb):

  • 申请
  • 国标变换
  • 国标过滤器
  • 国标聚合
  • GB 计数
  • gb.comsum
  • gb.fillna
  • ...

希望这有帮助:)