将具有一个单一分类值的列添加到 pandas 数据框
Adding a column with one single categorical value to a pandas dataframe
我有一个 pandas.DataFrame
df
,我想添加一个新列 col
,只有一个值 "hello"
。我希望此列是 dtype category
和单一类别 "hello"
。我可以做到以下几点。
df["col"] = "hello"
df["col"] = df["col"].astype("catgegory")
- 我真的需要写
df["col"]
三次 次才能实现吗?
- 在第一行之后,我担心中间数据框
df
在新列转换为分类之前可能会占用大量 space。 (数据框相当大,有数百万行,值 "hello"
实际上是一个更长的字符串。)
在避免上述问题的同时,是否还有其他直接、“简短”的方法来实现此目的?
另一种解决方案是
df["col"] = pd.Categorical(itertools.repeat("hello", len(df)))
但它需要 itertools
和 len(df)
的使用,我不确定内存使用情况。
这个解决方案肯定解决了第一点,第二点不确定:
df['col'] = pd.Categorical(('hello' for i in len(df)))
基本上
- 我们先创建一个'hello'的生成器,长度等于df中的记录数
- 然后我们将它传递给
pd.Categorical
使其成为分类列。
我们可以显式构建正确大小和类型的 Series,而不是通过 __setitem__
隐式构建然后转换:
df['col'] = pd.Series('hello', index=df.index, dtype='category')
示例程序:
import pandas as pd
df = pd.DataFrame({'a': [1, 2, 3]})
df['col'] = pd.Series('hello', index=df.index, dtype='category')
print(df)
print(df.dtypes)
print(df['col'].cat.categories)
a col
0 1 hello
1 2 hello
2 3 hello
a int64
col category
dtype: object
Index(['hello'], dtype='object')
一个简单的方法是使用 df.assign
创建新变量,然后使用 df.astype
以及特定列的数据类型字典将数据类型更改为 category
.
df = df.assign(col="hello").astype({'col':'category'})
df.dtypes
A int64
col category
dtype: object
这样你就不必创建一系列长度等于数据帧。您可以直接广播输入字符串,这样会节省更多时间和内存。
如您所见,这种方法的可扩展性很强。您可以根据需要分配多个变量,一些变量也基于复杂的功能。然后根据需要为它们设置数据类型。
df = pd.DataFrame({'A':[1,2,3,4]})
df = (df.assign(col1 = 'hello', #Define column based on series or broadcasting
col2 = lambda x:x['A']**2, #Define column based on existing columns
col3 = lambda x:x['col2']/x['A']) #Define column based on previously defined columns
.astype({'col1':'category',
'col2':'float'}))
print(df)
print(df.dtypes)
A col1 col2 col3
0 1 hello 1.0 1.0
1 2 hello 4.0 2.0
2 3 hello 9.0 3.0
3 4 hello 16.0 4.0
A int64
col1 category #<-changed dtype
col2 float64 #<-changed dtype
col3 float64
dtype: object
我有一个 pandas.DataFrame
df
,我想添加一个新列 col
,只有一个值 "hello"
。我希望此列是 dtype category
和单一类别 "hello"
。我可以做到以下几点。
df["col"] = "hello"
df["col"] = df["col"].astype("catgegory")
- 我真的需要写
df["col"]
三次 次才能实现吗? - 在第一行之后,我担心中间数据框
df
在新列转换为分类之前可能会占用大量 space。 (数据框相当大,有数百万行,值"hello"
实际上是一个更长的字符串。)
在避免上述问题的同时,是否还有其他直接、“简短”的方法来实现此目的?
另一种解决方案是
df["col"] = pd.Categorical(itertools.repeat("hello", len(df)))
但它需要 itertools
和 len(df)
的使用,我不确定内存使用情况。
这个解决方案肯定解决了第一点,第二点不确定:
df['col'] = pd.Categorical(('hello' for i in len(df)))
基本上
- 我们先创建一个'hello'的生成器,长度等于df中的记录数
- 然后我们将它传递给
pd.Categorical
使其成为分类列。
我们可以显式构建正确大小和类型的 Series,而不是通过 __setitem__
隐式构建然后转换:
df['col'] = pd.Series('hello', index=df.index, dtype='category')
示例程序:
import pandas as pd
df = pd.DataFrame({'a': [1, 2, 3]})
df['col'] = pd.Series('hello', index=df.index, dtype='category')
print(df)
print(df.dtypes)
print(df['col'].cat.categories)
a col
0 1 hello
1 2 hello
2 3 hello
a int64
col category
dtype: object
Index(['hello'], dtype='object')
一个简单的方法是使用 df.assign
创建新变量,然后使用 df.astype
以及特定列的数据类型字典将数据类型更改为 category
.
df = df.assign(col="hello").astype({'col':'category'})
df.dtypes
A int64
col category
dtype: object
这样你就不必创建一系列长度等于数据帧。您可以直接广播输入字符串,这样会节省更多时间和内存。
如您所见,这种方法的可扩展性很强。您可以根据需要分配多个变量,一些变量也基于复杂的功能。然后根据需要为它们设置数据类型。
df = pd.DataFrame({'A':[1,2,3,4]})
df = (df.assign(col1 = 'hello', #Define column based on series or broadcasting
col2 = lambda x:x['A']**2, #Define column based on existing columns
col3 = lambda x:x['col2']/x['A']) #Define column based on previously defined columns
.astype({'col1':'category',
'col2':'float'}))
print(df)
print(df.dtypes)
A col1 col2 col3
0 1 hello 1.0 1.0
1 2 hello 4.0 2.0
2 3 hello 9.0 3.0
3 4 hello 16.0 4.0
A int64
col1 category #<-changed dtype
col2 float64 #<-changed dtype
col3 float64
dtype: object