我试图替换一个数据框架的一列的值。列('female')只包含值'female'和'male'。

我尝试过以下方法:

w['female']['female']='1'
w['female']['male']='0' 

但收到的是与之前结果完全相同的副本。

理想情况下,我希望得到类似于以下循环元素的输出。

if w['female'] =='female':
    w['female'] = '1';
else:
    w['female'] = '0';

我已经查看了gotchas文档(http://pandas.pydata.org/pandas-docs/stable/gotchas.html),但不明白为什么什么都没有发生。

任何帮助都将不胜感激。


当前回答

为了更一般地回答这个问题,使它适用于更多的用例,而不仅仅是OP要求的用例,可以考虑这个解决方案。我使用jfs的解决方案来帮助我。在这里,我们创建了两个相互帮助的函数,无论您是否知道确切的替换都可以使用它们。

import numpy as np
import pandas as pd


class Utility:

    @staticmethod
    def rename_values_in_column(column: pd.Series, name_changes: dict = None) -> pd.Series:
        """
        Renames the distinct names in a column. If no dictionary is provided for the exact name changes, it will default
        to <column_name>_count. Ex. female_1, female_2, etc.

        :param column: The column in your dataframe you would like to alter.
        :param name_changes: A dictionary of the old values to the new values you would like to change.
        Ex. {1234: "User A"} This would change all occurrences of 1234 to the string "User A" and leave the other values as they were.
        By default, this is an empty dictionary.
        :return: The same column with the replaced values
        """
        name_changes = name_changes if name_changes else {}
        new_column = column.replace(to_replace=name_changes)
        return new_column

    @staticmethod
    def create_unique_values_for_column(column: pd.Series, except_values: list = None) -> dict:
        """
        Creates a dictionary where the key is the existing column item and the value is the new item to replace it.
        The returned dictionary can then be passed the pandas rename function to rename all the distinct values in a
        column.
        Ex. column ["statement"]["I", "am", "old"] would return
        {"I": "statement_1", "am": "statement_2", "old": "statement_3"}

        If you would like a value to remain the same, enter the values you would like to stay in the except_values.
        Ex. except_values = ["I", "am"]
        column ["statement"]["I", "am", "old"] would return
        {"old", "statement_3"}

        :param column: A pandas Series for the column with the values to replace.
        :param except_values: A list of values you do not want to have changed.
        :return: A dictionary that maps the old values their respective new values.
        """
        except_values = except_values if except_values else []
        column_name = column.name
        distinct_values = np.unique(column)
        name_mappings = {}
        count = 1
        for value in distinct_values:
            if value not in except_values:
                name_mappings[value] = f"{column_name}_{count}"
                count += 1
        return name_mappings

对于OP的用例,使用它非常简单

w["female"] = Utility.rename_values_in_column(w["female"], name_changes = {"female": 0, "male":1}

然而,要知道您想要重命名的数据帧中所有不同的惟一值并不总是那么容易。在我的例子中,列的字符串值是散列值,因此它们损害了可读性。我所做的是使用create_unique_values_for_column函数将这些散列值替换为更可读的字符串。

df["user"] = Utility.rename_values_in_column(
    df["user"],
    Utility.create_unique_values_for_column(df["user"])
)

这将改变我的用户列值从["1a2b3c", "a12b3c","1a2b3c"]到["user_1", "user_2", "user_1]。比较起来容易多了,对吧?

其他回答

如果我没理解错的话,你想要这样的东西:

w['female'] = w['female'].map({'female': 1, 'male': 0})

(这里我将值转换为数字,而不是包含数字的字符串。你可以把它们转换成“1”和“0”,如果你真的想,但我不知道为什么你想这样做。)

你的代码不能工作的原因是因为在列上使用['female'] (w['female']['female']中的第二个'female')并不意味着“选择值为'female'的行”。这意味着选择索引为“female”的行,而这些行在你的DataFrame中可能没有。

轻微的变化:

w.female.replace(['male', 'female'], [1, 0], inplace=True)

pandas中还有一个叫做factorize的函数,您可以使用它自动完成这类工作。它将标签转换为数字:['male', 'female', 'male'] ->[0,1,0]。更多信息请看这个答案。

我认为,在答案应该指出哪种类型的对象,你得到的所有方法上面建议:它是系列或数据帧。

当你看到w。female的专栏。或者w[[2]](其中,假设2是你的列的数字),你会得到DataFrame。 在这种情况下,你可以使用DataFrame方法,比如。replace。

当你使用。loc或iloc时,你会返回Series,而Series没有。replace方法,所以你应该使用apply, map等方法。

这非常紧凑:

w['female'][w['female'] == 'female']=1
w['female'][w['female'] == 'male']=0

另一个好例子:

w['female'] = w['female'].replace(regex='female', value=1)
w['female'] = w['female'].replace(regex='male', value=0)