使用Python Pandas将数据框中的字符串替换为数字。

60

有没有办法使用映射函数或更好的方法来替换整个数据框中的值?

我只知道如何在系列上执行映射。

我想用一个数字替换“tesst”和“set”列中的字符串,例如set = 1,test =2。

这是我的数据集示例:(原始数据集非常大)

ds_r
  respondent  brand engine  country  aware  aware_2  aware_3  age tesst   set
0          a  volvo      p      swe      1        0        1   23   set   set
1          b  volvo   None      swe      0        0        1   45   set   set
2          c    bmw      p       us      0        0        1   56  test  test
3          d    bmw      p       us      0        1        1   43  test  test
4          e    bmw      d  germany      1        0        1   34   set   set
5          f   audi      d  germany      1        0        1   59   set   set
6          g  volvo      d      swe      1        0        0   65  test   set
7          h   audi      d      swe      1        0        0   78  test   set
8          i  volvo      d       us      1        1        1   32   set   set

最终结果应该是

 ds_r
  respondent  brand engine  country  aware  aware_2  aware_3  age  tesst  set
0          a  volvo      p      swe      1        0        1   23      1    1
1          b  volvo   None      swe      0        0        1   45      1    1
2          c    bmw      p       us      0        0        1   56      2    2
3          d    bmw      p       us      0        1        1   43      2    2
4          e    bmw      d  germany      1        0        1   34      1    1
5          f   audi      d  germany      1        0        1   59      1    1
6          g  volvo      d      swe      1        0        0   65      2    1
7          h   audi      d      swe      1        0        0   78      2    1
8          i  volvo      d       us      1        1        1   32      1    1
10个回答

90

那么 DataFrame.replace 呢?

In [9]: mapping = {'set': 1, 'test': 2}

In [10]: df.replace({'set': mapping, 'tesst': mapping})
Out[10]: 
   Unnamed: 0 respondent  brand engine  country  aware  aware_2  aware_3  age  \
0           0          a  volvo      p      swe      1        0        1   23   
1           1          b  volvo   None      swe      0        0        1   45   
2           2          c    bmw      p       us      0        0        1   56   
3           3          d    bmw      p       us      0        1        1   43   
4           4          e    bmw      d  germany      1        0        1   34   
5           5          f   audi      d  germany      1        0        1   59   
6           6          g  volvo      d      swe      1        0        0   65   
7           7          h   audi      d      swe      1        0        0   78   
8           8          i  volvo      d       us      1        1        1   32   

  tesst set  
0     2   1  
1     1   2  
2     2   1  
3     1   2  
4     2   1  
5     1   2  
6     2   1  
7     1   2  
8     2   1  

正如 @Jeff 在评论中指出的那样,在Pandas版本 < 0.11.1中,需要手动添加 .convert_objects() 来正确地将tesst和set转换为 int64列,以防在后续操作中出现问题。


1
请注意,在替换后,您可能需要执行“df.convert_objects()”以强制转换为适当的数据类型。 - Jeff
1
@Dan Allan 这将在0.11.1中成为默认设置,供您参考(用于convert_objects)。 - Jeff
8
这段话很古老,但现在你也可以这样做:df.replace(to_replace=['set', 'test'], value=[1, 2])。该代码的作用是将DataFrame中所有等于'set'的值替换为1,将所有等于'test'的值替换为2。 - Ishnark
我认为我们不应该要求硬编码值的名称,它应该在运行时动态地选择并分配编号。 - H S Rathore

32

我知道这篇文章很老了,但是我还是想分享我的经验。在这段代码中创建一个 pandas 数据帧,命名为 df。

ip_addresses = df.source_ip.unique()
ip_dict = dict(zip(ip_addresses, range(len(ip_addresses))))

这将为您提供IP地址的字典映射,而无需将其写出。


17
你可以使用applymap DataFrame函数来实现这个目的:
In [26]: df = DataFrame({"A": [1,2,3,4,5], "B": ['a','b','c','d','e'],
                         "C": ['b','a','c','c','d'], "D": ['a','c',7,9,2]})
In [27]: df
Out[27]:
   A  B  C  D
0  1  a  b  a
1  2  b  a  c
2  3  c  c  7
3  4  d  c  9
4  5  e  d  2

In [28]: mymap = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}

In [29]: df.applymap(lambda s: mymap.get(s) if s in mymap else s)
Out[29]:
   A  B  C  D
0  1  1  2  1
1  2  2  1  3
2  3  3  3  7
3  4  4  3  9
4  5  5  4  2

我正在解决这样的问题,我只是按照你回答中提到的确切步骤进行操作。但是我没有得到输出结果。 代码: wc = pd.read_csv('路径', usecols = ['工作类别']) - SRS
df = pd.DataFrame(wc) 行末 wcdict = {"?":0,"Federal-gov":1,"Local-gov":2,"Never-worked":3,"Private":4,"Self-emp-inc":5, "Self-emp-n-inc":6,"State-gov":7,"Without-pay":8} 行末 df.applymap(lambda s: wcdict.get(s) if s in wcdict else s) 行末 print(df) - SRS
df.applymap(lambda s: mymap.get(s) if s in mymap else s) 不会对 df 进行内联更改,因此您的 print df 语句不会反映 applymap 的结果。 您需要执行类似 df2 = df.applymap(lambda s: mymap.get(s) if s in mymap else s) 的赋值操作。 现在,print df2 将反映更改。 - bdiamante
成功了!谢谢 :) 我还有一个问题,我需要使用pyspark而不是普通的python。在pyspark中实现这个逻辑是否有所不同?当我创建一个数据框时,我给出了文件路径[如上面的评论所示],但我想将RDD作为输入给数据框。我做不到。你有什么想法吗? - SRS
很高兴它起作用了。我真的不确定...也许这个可以作为一个开始? - bdiamante
感谢您的帮助 :) - SRS

11

在数据框中替换任何值的最简单方法:

df=df.replace(to_replace="set",value="1")
df=df.replace(to_replace="test",value="2")

希望这能够帮到您。

8

将类似于 "沃尔沃","宝马" 的字符串转换为整数,首先将其转换为数据框,然后传递给pandas.get_dummies()函数。

  df  = DataFrame.from_csv("myFile.csv")
  df_transform = pd.get_dummies( df )
  print( df_transform )

更好的替代方法:将一个字典传递给pandas系列(df.myCol)的map()函数(例如,指定列品牌)。
df.brand = df.brand.map( {'volvo':0 , 'bmw':1, 'audi':2} )

2
你也可以使用pandas的rename_categories方法来实现这个功能。首先需要将列定义为dtype="category"类型。例如:
In [66]: s = pd.Series(["a","b","c","a"], dtype="category")

In [67]: s
Out[67]: 
0    a
1    b
2    c
3    a
dtype: category
Categories (3, object): [a, b, c]

然后将它们重命名:

In [70]: s.cat.rename_categories([1,2,3])
Out[70]: 
0    1
1    2
2    3
3    1
dtype: category
Categories (3, int64): [1, 2, 3]

你也可以传递类似字典的对象进行重命名映射,例如:

In [72]: s.cat.rename_categories({1: 'x', 2: 'y', 3: 'z'})

一般来说,这个类别类型是用来做什么的? - HerrIvan
@HerrIvan 这里有大量的文档 https://pandas.pydata.org/pandas-docs/stable/categorical.html - tsando

2
当功能不是很多时:
mymap = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}
df.applymap(lambda s: mymap.get(s) if s in mymap else s)

当无法手动操作时:

temp_df2 = pd.DataFrame({'data': data.data.unique(), 'data_new':range(len(data.data.unique()))})# create a temporary dataframe 
data = data.merge(temp_df2, on='data', how='left')# Now merge it by assigning different values to different strings.

1

pandas.factorize() 正是做这件事情的。

>>> codes, uniques = pd.factorize(['b', 'b', 'a', 'c', 'b'])
>>> codes
array([0, 0, 1, 2, 0]...)
>>> uniques
array(['b', 'a', 'c'], dtype=object)

使用DataFrame:

df["tesst"], tesst_key = pandas.factorize(df["tesst"])

1
你可以根据列值本身构建一个 字典 并按以下方式填充
x=df['Item_Type'].value_counts()
item_type_mapping={}
item_list=x.index
for i in range(0,len(item_list)):
    item_type_mapping[item_list[i]]=i

df['Item_Type']=df['Item_Type'].map(lambda x:item_type_mapping[x]) 

0

df.replace(to_replace=['set', 'test'], value=[1, 2]) 来自 @Ishnark 在被采纳的答案中的评论。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接