Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python按多列分组,创建字符串列表,但对数字求和_Python_Pandas_Pandas Groupby - Fatal编程技术网

Python按多列分组,创建字符串列表,但对数字求和

Python按多列分组,创建字符串列表,但对数字求和,python,pandas,pandas-groupby,Python,Pandas,Pandas Groupby,目前,我的数据帧看起来类似于: ID Year Str1 Str2 Value 0 1 2014 high black 120 1 1 2015 high blue 20 2 2 2014 medium red 10 3 2 2014 medium blue 50 4 3 2015 low blue 30 5 3

目前,我的数据帧看起来类似于:

     ID  Year   Str1     Str2     Value
0    1   2014   high     black    120
1    1   2015   high     blue     20
2    2   2014   medium   red      10
3    2   2014   medium   blue     50
4    3   2015   low      blue     30
5    3   2015   high     blue     .5
6    3   2015   high     red      10
期望的:

     ID  Year   Str1        Str2          Value
0    1   2014   high        black         120
1    1   2015   high        blue          20
2    2   2014   medium      red, blue     60
3    3   2015   low, high   blue, red     40.5
尝试按列ID和列名称分组,然后获取数字的总和,但得到一个字符串列表。如果可以像示例中那样删除重复的字符串,这将很有帮助,但不是必需的

此操作将对大约100个数据帧执行,ID和Year是每个数据帧中唯一可以找到的列名。数据帧确实略有不同:它们有value列、str列或两者兼有

我浏览了很多stackoverflow并尝试:

df.groupby(['ID', 'Year'], as_index=False).agg(lambda x: x.sum() if x.dtype=='int64' else ', '.join(x))
导致错误的DataFrame对象没有属性dtype(这很有意义,因为按多列分组会返回更多的数据帧)

我还试着一列一列地循环,如果列中有数字,它会计算总数,否则会列出一个列表:

for col in df:
    if col in ['ID', 'Year']:
        continue 

    if df[col].dtype.kind == 'i' or df[col].dtype.kind == 'f':
         df = df.groupby(['ID', 'Year'])[col].apply(sum)
    else:
         df = df.groupby(['ID', 'Year'])[col].unique().reset_index()
但是,在第一次执行该操作后,它去掉了所有其他列


提前感谢。

您需要检查
数值列是否为
列,例如:



我有一个类似的问题,所以假设我有一个这样的数据列,我想通过电子邮件分组,并对不同的列执行不同的agg函数,所以标准的groupby函数不够好

无论如何,这里有一个虚拟数据集:

    Email            Phone          State
0   email@gmail.com 123-456-7890    NY
1   email@gmail.com 321-654-0987    LA
2   person@gmail.com    123-789-4567    WA
3   dummy@gmail.com 873-345-3456    MN
4   dummy@gmail.com 123-345-3456    NY
5   email@gmail.com 000-000-0000    KY
知道哪一个是第一个被复制的项目会很有用,所以我们会处理它,而忽略其他项目。首先,我要标记第一个重复项

这看起来很复杂,但它所做的是:获取所有复制的
真实VAL列表
,并对所有第一个复制的
真实VAL列表执行and操作。

df["first_dupe"] = df.duplicated("Email", keep=False) & ~df.duplicated("Email", keep="first")
然后将此函数应用于数据帧:

def combine_rows(row, key="Email", cols_to_combine=["Phone", "State"]):
    """takes in a row, looks at the key column
        if its the first dupe, combines the data in cols_to_combine with the other rows with same key
        needs a dataframe with a bool column first_dupe with True if the row is the first dupe"""

    if row["first_dupe"] == True:
        # making a df of dupes item
        dupes = df[df[key]==row[key]]

        for i, dupe_row in dupes.iloc[1:].iterrows():   # skipping the first row, since thats our first_dupe
            for col in cols_to_combine:
                row[col] += ", " + dupe_row[col]
        # make sure first_dupe doesn't get processed again
        row.first_dupe = False  
    return row

df = df.apply(combine_rows, axis=1, result_type=None)

您可以修改combine rows函数,对不同的列执行不同的操作。

如果有人遇到奇怪的行为,而不是获得正确的列表/总和,您会得到每行的列名列表,数据中可能有NaN值。将NaN值替换为
df=df。需要使用fillna(“”)
才能工作。
df["first_dupe"] = df.duplicated("Email", keep=False) & ~df.duplicated("Email", keep="first")
def combine_rows(row, key="Email", cols_to_combine=["Phone", "State"]):
    """takes in a row, looks at the key column
        if its the first dupe, combines the data in cols_to_combine with the other rows with same key
        needs a dataframe with a bool column first_dupe with True if the row is the first dupe"""

    if row["first_dupe"] == True:
        # making a df of dupes item
        dupes = df[df[key]==row[key]]

        for i, dupe_row in dupes.iloc[1:].iterrows():   # skipping the first row, since thats our first_dupe
            for col in cols_to_combine:
                row[col] += ", " + dupe_row[col]
        # make sure first_dupe doesn't get processed again
        row.first_dupe = False  
    return row

df = df.apply(combine_rows, axis=1, result_type=None)