Pandas 1.0.0 est sorti le 29 janvier 2020! Crépitement Depuis le 14/02/2020, il s'agit du 1.0.1.
Personnellement, je pense que les changements suivants sont des points importants.
--pandas original NA
--Expérimental pour le type String
Bien.
Lors de l'analyse, j'utilise souvent les bibliothèques et pandas suivants ensemble.
En particulier, j'aimerais connaître l'état du support de dask pour pandas 1.0 et d'autres comportements détaillés. La version de dask est la 2.10.1 au 14/02/2020.
Concernant les apports, je pense qu'il n'y a pas de problème si dask le soutient. (Il y a aussi un moment où le temps d'attente de traitement de dask est libre.)
pandas.NA
? (Lié à la version 1.0)dtype: string
? (Lié à la version 1.0)pandas.NA
ou dtype: string
? (Lié à la version 1.0)
――Non, pouvez-vous utiliser correctement dask avec dtype: categorical
? (Autre)Tom Augspurger semble soutenir les pandas 1.0 comme un démon, et j'ai de grandes attentes jusqu'à présent.
Pour ceux qui ne veulent connaître que le résultat.
--Dask peut exécuter quatre règles et opérations sur des chaînes même s'il contient pandas.NA
.
--dask ne peut pas être set_index
avec des types personnalisés tels que ʻInt64,
string --Les deux pandas / dask ne peuvent pas indexer le filtre sur les colonnes
booléennes contenant
pandas.NA --dask devient le type ʻobject
même si ʻapply (meta = 'string') , mais il est réactivé par ʻas type ('string')
.
lors de l'ajout d'une nouvelle colonne catégorielle au dask DataFrame --dask ne peut pas to_parquet types ʻInt64
et string
(quand engine = fastparquet).Pour le moment, préparez un environnement de vérification propre.
Le système d'exploitation est macOS Catalina 10.15.2
.
En ce qui concerne la version python, les pandas ne définissent que le minimum, et dask semble être compatible python3.8, donc Si c'est 3.7.4
, il n'y aura pas de problème.
Pour les dépendances, incluez versions minimales pour les dépendances. Cependant, fastparquet et pyArrow ne peuvent pas coexister sur mac problème utilisé pour exister, donc pyArrow ne doit pas être inclus juste au cas où. Je ne m'en sers pas.
Le travail de vérification est effectué sur jupyterlab.
pyenv virtualenv 3.7.4 pandas100
pyenv shell pandas100
pip install -r requirements.txt
requirements.txt
pandas==1.0.1
dask[complete]==2.10.1
fastparquet==0.3.3
jupyterlab==1.2.6
numpy==1.18.1
pytz==2019.3
python-dateutil==2.8.1
numexpr==2.7.1
beautifulsoup4==4.8.2
gcsfs==0.6.0
lxml==4.5.0
matplotlib==3.1.3
numba==0.48.0
openpyxl==3.0.3
pymysql==0.9.3
tables==3.6.1
s3fs==0.4.0
scipy==1.4.1
sqlalchemy==1.3.13
xarray==0.15.0
xlrd==1.2.0
xlsxwriter==1.2.7
xlwt==1.3.0
dask vs pandas1.0
Commencez par vérifier pd.NA.
Vérifiez le comportement de pd.NA dans chaque
s=... |
type(s.loc[3]) |
---|---|
pandas.Series([1,2,3,None], dtype='int') | TypeError |
pandas.Series([1,2,3,pandas.NA], dtype='int') | TypeError |
pandas.Series([1,2,3,None], dtype='Int64') | pandas._libs.missing.NAType |
pandas.Series([1,2,3,None], dtype='float') | numpy.float64 |
pandas.Series([1,2,3,pandas.NA], dtype='float') | TypeError |
pandas.Series([1,2,3,None], dtype='Int64').astype('float') | numpy.float64 |
pandas.Series(['a', 'b', 'c' ,None], dtype='string') | pandas._libs.missing.NAType |
pandas.Series(['a', 'b', 'c' ,None], dtype='object').astype('string') | pandas._libs.missing.NAType |
pandas.Series([True, False, True ,None], dtype='boolean') | pandas._libs.missing.NAType |
pandas.Series([1, 0, 1 ,None], dtype='float').astype('boolean') | pandas._libs.missing.NAType |
pandas.Series(pandas.to_datetime(['2020-01-01', '2020-01-02', '2020-01-03', None])) | pandas._libs.tslibs.nattype.NaTType |
pandas.Series(pandas.to_timedelta(['00:00:01', '00:00:02', '00:00:03', None])) | pandas._libs.tslibs.nattype.NaTType |
pandas.Series([object(), object(), object(), None], dtype='object') | NoneType |
pandas.Series([object(), object(), object(), pandas.NA], dtype='object') | pandas.Series([object(), object(), object(), pandas.NA], dtype='object') |
Résumé,
--dtype int ne devient pas pandas.NA
(TypeError tel quel)
--dtype Int64, chaîne, booléen devient pandas.NA
.
--dtype float devient numpy.NaN
--dtype datetime64, timedelta64 devient NAT
L'objet --dtype ne convertit pas automatiquement None
en pandas.NA
Examinez ce qui se passe quand il s'agit de dask.dataframe.from_pandas
.
>>> import pandas
>>> import dask.dataframe
>>> df = pandas.DataFrame({'i': [1,2,3,4],
... 'i64': pandas.Series([1,2,3,None], dtype='Int64'),
... 's': pandas.Series(['a', 'b', 'c' ,None], dtype='string'),
... 'f': pandas.Series([1,2,3,None], dtype='Int64').astype('float')})
>>> ddf = dask.dataframe.from_pandas(df, npartitions=1)
>>> df
i i64 s f
0 1 1 a 1.0
1 2 2 b 2.0
2 3 3 c 3.0
3 4 <NA> <NA> NaN
>>> ddf
Dask DataFrame Structure:
i i64 s f
npartitions=1
0 int64 Int64 string float64
3 ... ... ... ...
En effet, ʻInt64 est aussi ʻInt64
sur dask. La même chose s'applique à "string".
>>> #(Entier) opération sur Int64
>>> df.i64 * 2
0 2
1 4
2 6
3 <NA>
Name: i64, dtype: Int64
>>> (ddf.i64 * 2).compute()
0 2
1 4
2 6
3 <NA>
Name: i64, dtype: Int64
Le traitement Int64-> Int64 fonctionne correctement.
>>> #(Score minoritaire flottant) calcul pour Int64
>>> df.i64 - df.f
0 0.0
1 0.0
2 0.0
3 NaN
dtype: float64
>>> (ddf.i64 - ddf.f).compute()
0 0.0
1 0.0
2 0.0
3 NaN
dtype: float64
Le traitement Int64-> float64 fonctionne également correctement.
>>> # pandas.Défini dans la colonne Int64 contenant NA_index
>>> df.set_index('i64')
i s f i64_result i64-f
i64
1 1 a 1.0 2 0.0
2 2 b 2.0 4 0.0
3 3 c 3.0 6 0.0
NaN 4 <NA> NaN <NA> NaN
>>> ddf.set_index('i64').compute()
TypeError: data type not understood
>>> # pandas.Que se passerait-il sans NA
>>> ddf['i64_nonnull'] = ddf.i64.fillna(1)
... ddf.set_index('i64_nonnull').compute()
TypeError: data type not understood
Eh! dask ne peut pas set_index
dans la colonne ʻInt64`!
Bien sûr, les pandas le peuvent.
>>> # pandas.Définir dans la colonne de chaîne contenant NA_index
>>> df.set_index('s')
i i64 f
s
a 1 1 1.0
b 2 2 2.0
c 3 3 3.0
NaN 4 <NA> NaN
>>> ddf.set_index('s').compute()
TypeError: Cannot perform reduction 'max' with string dtype
>>> # pandas.Que se passerait-il sans NA
>>> ddf['s_nonnull'] = ddf.s.fillna('a')
... ddf.set_index('s_nonnull')
TypeError: Cannot perform reduction 'max' with string dtype
Je ne peux pas non plus faire de string
. Cela ne peut pas encore être utilisé (dans mon utilisation).
# .Essayez la fonction str
>>> df.s.str.startswith('a')
0 True
1 False
2 False
3 <NA>
Name: s, dtype: boolean
>>> ddf.s.str.startswith('a').compute()
0 True
1 False
2 False
3 <NA>
Name: s, dtype: boolean
Hmmm, ça marche.
>>> # pandas.Filtrer par colonne booléenne contenant NA
>>> df[df.s.str.startswith('a')]
ValueError: cannot mask with array containing NA / NaN values
>>> # pandas.Est-ce que NA est mauvais?
>>> df['s_nonnull'] = df.s.fillna('a')
... df[df.s_nonnull.str.startswith('a')]
i i64 s f i64_nonnull s_nonnull
0 1 1 a 1.0 1 a
3 4 <NA> <NA> NaN 1 a
>>> ddf[ddf.s.str.startswith('a')].compute()
ValueError: cannot mask with array containing NA / NaN values
>>> ddf['s_nonnull'] = ddf.s.fillna('a')
... ddf[ddf.s_nonnull.str.startswith('a')].compute()
i i64 s f i64_nonnull s_nonnull
0 1 1 a 1.0 1 a
3 4 <NA> <NA> NaN 1 a
>>> ddf[ddf.s.str.startswith('a')].compute()
e! !! !! Vous ne pouvez pas filtrer si pandas.NA est inclus? Ce n'est pas bien!
>>> #appliquer à meta='Int64'Essayez de spécifier
>>> ddf['i10'] = ddf.i.apply(lambda v: v * 10, meta='Int64')
>>> ddf
Dask DataFrame Structure:
i i64 s f i64_nonnull s_nonnull i10
npartitions=1
0 int64 Int64 string float64 Int64 string int64
3 ... ... ... ... ... ... ...
>>> #appliquer à meta='string'Essayez de spécifier
>>> ddf['s_double'] = ddf.s.apply(lambda v: v+v, meta='string')
Dask DataFrame Structure:
i i64 s f i64_nonnull s_nonnull i10 s_double
npartitions=1
0 int64 Int64 string float64 Int64 string int64 object
3 ... ... ... ... ... ... ... ...
>>> # astype('string')Essayer
>>> ddf['s_double'] = ddf['s_double'].astype('string')
>>> ddf
Dask DataFrame Structure:
i i64 s f i64_nonnull s_nonnull i10 s_double
npartitions=1
0 int64 Int64 string float64 Int64 string int64 string
3 ... ... ... ... ... ... ... ...
Si vous le spécifiez avec meta =, n'est-il pas reflété? .. .. Il peut être réactivé avec un type, mais c'est un problème. .. ..
--Le calcul est OK --Dans dask, il ne peut pas être utilisé comme index (car le type qui prend en charge pandas.NA ne peut pas être utilisé en premier lieu)
dask vs pandas.Categorical
Afin d'enquêter sur le catégorique chez les pandas, cette fois, nous utiliserons la méthode utilisant le Dtype catégorique. L'utilisation de base de Dtype catégorique est
Je pense que c'est. Exemple de code ci-dessous
>>> #Tout d'abord, créez un Dtype catégorique
>>> int_category = pandas.CategoricalDtype(categories=[1,2,3,4,5],
... ordered=True)
>>> int_category
CategoricalDtype(categories=[1, 2, 3, 4, 5], ordered=True)
>>> int_category.categories
Int64Index([1, 2, 3, 4, 5], dtype='int64')
>>> #Comme ces pandas.Faire une série
>>> int_series = pandas.Series([1,2,3], dtype=int_category)
>>> int_series
0 1
1 2
2 3
dtype: category
Categories (5, int64): [1 < 2 < 3 < 4 < 5]
>>> #Au moment de la génération, il convertira les valeurs qui ne sont pas dans la catégorie en NaN
>>> int_series = pandas.Series([1,2,3,6], dtype=int_category)
>>> int_series
0 1
1 2
2 3
3 NaN
dtype: category
Categories (5, int64): [1 < 2 < 3 < 4 < 5]
>>> #Se mettre en colère après génération
>>> int_series.loc[3] = 10
ValueError: Cannot setitem on a Categorical with a new category, set the categories first
Ensuite, essayez d'utiliser Categorical sur dask.
>>> import pandas
>>> import dask.dataframe
>>> # pandas.Générer DataFrame
>>> df = pandas.DataFrame({'a': pandas.Series([1, 2, 3, 1, 2, 3], dtype=int_category),
... 'b': pandas.Series([1, 2, 3, 1, 2, 3], dtype='int64')})
>>> df
a b
0 1 1
1 2 2
2 3 3
3 1 1
4 2 2
5 3 3
>>> # dask.dataframe.Convertir en DataFrame
>>> ddf = dask.dataframe.from_pandas(df, npartitions=1)
>>> ddf
Dask DataFrame Structure:
a b
npartitions=1
0 category[known] int64
5 ... ...
Pour le moment, j'ai pu le rendre dask car c'est catégorique.
#L'ajout de nouvelles valeurs de catégorie est légal dans les pandas
>>> df.loc[2, 'a'] = 30
ValueError: Cannot setitem on a Categorical with a new category, set the categories first
#Dans dask, il ne peut pas être attribué en premier lieu indépendamment de la catégorie
>>> ddf.loc['a', 3] = 10
TypeError: '_LocIndexer' object does not support item assignment
#Chez les pandas, le calcul des valeurs de catégorie est également légal
>>> df.a * 2
TypeError: unsupported operand type(s) for *: 'Categorical' and 'int'
#Même avec dask, le calcul des valeurs de catégorie est légal
>>> ddf.a * 2
TypeError: unsupported operand type(s) for *: 'Categorical' and 'int'
#Essayez de spécifier comme méta avec appliquer de dask
>>> ddf['c'] = ddf.a.apply(lambda v: v, meta=int_category)
Dont know how to create metadata from category
#dask appliquer, meta='category'Ferez-vous de votre mieux si vous le faites?
>>> ddf['c'] = ddf.a.apply(lambda v: v, meta='category')
>>> ddf.dtypes
a category
b int64
c object
dtype: object
>>> #Vérifiez s'il est cohérent avec le contenu
>>> ddf.compute().dtypes
a category
b int64
c category
dtype: object
>>> #essayez un type
>>> ddf['c'] = ddf.c.astype(int_category)
>>> ddf
Dask DataFrame Structure:
a b c
npartitions=1
0 category[known] int64 category[known]
5 ... ... ...
Je vois. La partie contrainte de la catégorie est maintenue, mais si vous faites .apply (meta =)
, la gestion dtype de dask sera boguée.
Il est possible de le relancer avec astype, mais c'est un problème. .. ..
N'est-il pas possible d'utiliser uniquement des filtres?
#Essayez d'agréger
>>> ddf.groupby('a').b.mean().compute()
a
1 1.0
2 2.0
3 3.0
4 NaN
5 NaN
Name: b, dtype: float64
#Le type n'est-il pas cassé en étant traité comme un index?
Dask DataFrame Structure:
a b
npartitions=1
category[known] float64
... ...
Dask Name: reset_index, 34 tasks
Hmmm, pensez-vous que cela correspond à l'agrégation?
--Lors de l'utilisation de pandas.Catégorique avec dask, les filtres et les agrégats semblent bien --Utilisez ʻas type` lorsque vous voulez ajouter une nouvelle colonne catégorielle au dask DataFrame.
to_parquet vs pandas1.0
>>> #Tout d'abord, les pandas.Générer DataFrame
>>> df = pandas.DataFrame(
{
'i64': pandas.Series([1, 2, 3,None], dtype='Int64'),
'i64_nonnull': pandas.Series([1, 2, 3, 4], dtype='Int64'),
's': pandas.Series(['a', 'b', 'c',None], dtype='string'),
's_nonnull': pandas.Series(['a', 'b', 'c', 'd'], dtype='string'),
}
)
>>> df
i64 i64_nonnull s s_nonnull
0 1 1 a a
1 2 2 b b
2 3 3 c c
3 <NA> 4 <NA> d
>>> # dask.dataframe.Convertir en DataFrame
>>> ddf = dask.dataframe.from_pandas(df, npartitions=1)
>>> ddf
Dask DataFrame Structure:
i64 i64_nonnull s s_nonnull
npartitions=1
0 Int64 Int64 string string
3 ... ... ... ...
Pour le moment, essayez to_parquet.
>>> ddf.to_parquet('test1', engine='fastparquet')
ValueError: Dont know how to convert data type: Int64
sérieusement. .. .. Je m'y attendais. .. .. Même si Int64 n'est pas bon, une chaîne peut être possible. .. ..
>>> ddf.to_parquet('test2', engine='fastparquet')
ValueError: Dont know how to convert data type: string
C'était mauvais.
--Int64 et string ne peuvent pas être to_parquet.
Comment était-ce? Peut-être que personne n'a lu ce commentaire jusqu'à la fin. Dois-je avoir séparé les messages?
pandas 1.0 J'espère que cela aidera les gens qui y réfléchissent.
À bientôt.
Recommended Posts