来自tidyverse

时间:2019-02-26 18:31:31

标签: python r data-science

我是R的狂热用户,并且正在学习python。我可以在R中轻松运行的示例代码之一使我感到困惑。

这是原始数据(在R中构造):

library(tidyverse)


df <- tribble(~name, ~age, ~gender, ~height_in,
        "john",20,'m',66,
        'mary',NA,'f',62,
        NA,38,'f',68,
        'larry',NA,NA,NA
)

输出如下:

df

# A tibble: 4 x 4
  name    age gender height_in
  <chr> <dbl> <chr>      <dbl>
1 john     20 m             66
2 mary     NA f             62
3 NA       38 f             68
4 larry    NA NA            NA

我想做三件事:

  1. 我想将字符列中的NA值替换为值“ zz”
  2. 我想将数字列中的NA值替换为0
  3. 我想将字符列转换为因数。

这是我在R中进行的操作(再次使用tidyverse程序包):

tmp <- df %>%
  mutate_if(is.character, function(x) ifelse(is.na(x),"zz",x)) %>%
  mutate_if(is.character, as.factor) %>%
  mutate_if(is.numeric, function(x) ifelse(is.na(x), 0, x))

这是数据帧tmp的输出:

tmp

# A tibble: 4 x 4
  name    age gender height_in
  <fct> <dbl> <fct>      <dbl>
1 john     20 m             66
2 mary      0 f             62
3 zz       38 f             68
4 larry     0 zz             0

我熟悉Python中的if()和else()语句。我不知道是在Python中执行上述代码的正确且最易读的方式。我猜想pandas包中没有mutate_if等效项。我的问题是,我可以在python中使用哪些类似的代码来模仿tidyverse和R中的mutate_if,is.character,is.numeric和as.factor函数?

另一方面,我对代码执行的速度/效率不是很感兴趣,而是对可读性感兴趣,这就是为什么我真正喜欢tidyverse的原因。如果有任何提示或建议,我将不胜感激。

编辑1:添加代码以创建熊猫数据框

这是我用来在Python中创建数据框的代码。这可能会帮助其他人入门。

import pandas as pd
import numpy as np

my_dict = {
    'name' : ['john','mary', np.nan, 'larry'],
    'age' : [20, np.nan, 38,  np.nan],
    'gender' : ['m','f','f', np.nan],
    'height_in' : [66, 62, 68, np.nan]
}

df = pd.DataFrame(my_dict)

其输出应类似:

print(df)
    name   age gender  height_in
0   john  20.0      m       66.0
1   mary   NaN      f       62.0
2    NaN  38.0      f       68.0
3  larry   NaN    NaN        NaN

2 个答案:

答案 0 :(得分:0)

好吧,睡一觉后,我想我已经解决了。

这是我用来获取pandas数据帧并应用前面提到的类似mutate_if函数以获得相同结果的代码。

# fill in the missing values (similar to mutate_if from tidyverse)
df1 = df.select_dtypes(include=['double']).fillna(0)
df2 = df.select_dtypes(include=['object']).fillna('zz').astype('category')

df = pd.concat([df2.reset_index(drop = True), df1], axis = 1)

print(df)
    name gender   age  height_in
0   john      m  20.0       66.0
1   mary      f   0.0       62.0
2     zz      f  38.0       68.0
3  larry     zz   0.0        0.0

# check again for the data types
df.dtypes
name         category
gender       category
age           float64
height_in     float64
dtype: object

要注意的是,我不得不“分解”原始数据框,应用更改(即,填写缺失值并更改数据类型),然后重新组合列(即,将数据框放回原处)

答案 1 :(得分:0)

一种与 tidyverse 方式一致的方式怎么样:

>>> from datar import f
>>> from datar.tibble import tribble
>>> from datar.base import NA, is_na, is_numeric, is_character, as_factor
>>> from datar.dplyr import mutate, across, where
>>> from datar.tidyr import replace_na
>>> # or if you are lazy
>>> # from datar.all import *
>>> 
>>> df = tribble(
...     f.name, f.age, f.gender, f.height_in,
...     "john", 20,    'm',      66,
...     'mary', NA,    'f',      62,
...     NA,     38,    'f',      68,
...     'larry',NA,    NA,       NA
... )
>>> 
>>> tmp = df >> \
...   mutate(across(where(is_character), replace_na, "zz")) >> \
...   mutate(across(where(is_character), as_factor)) >> \
...   mutate(across(where(is_numeric), replace_na, 0))
>>> 
>>> tmp
        name       age     gender  height_in
  <category> <float64> <category>  <float64>
0       john      20.0          m       66.0
1       mary       0.0          f       62.0
2         zz      38.0          f       68.0
3      larry       0.0         zz        0.0

我是 datar 包的作者。如果您对使用有任何疑问,请随时提交问题。