当前我的数据框看起来类似于:
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和Name列分组,然后获取数字总和,但列出字符串。如果像示例中那样可以删除重复的字符串,那将有所帮助,但这不是必需的。
此操作将对约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()
但是,第一次执行该操作后,它摆脱了所有其他列。
谢谢。
答案 0 :(得分:2)
您需要检查numeric
列,例如由this solution:
df = (df.groupby(['ID', 'Year'], as_index=False)
.agg(lambda x: x.sum() if np.issubdtype(x.dtype, np.number) else ', '.join(x)))
print (df)
ID Year Str1 Str2 Value
0 1 2014 high black 120.0
1 1 2015 high blue 20.0
2 2 2014 medium, medium red, blue 60.0
3 3 2015 low, high, high blue, blue, red 40.5
from pandas.api.types import is_numeric_dtype
df = (df.groupby(['ID', 'Year'], as_index=False)
.agg(lambda x: x.sum() if is_numeric_dtype(x) else ', '.join(x)))
答案 1 :(得分:1)
我有一个类似的问题,所以说我有一个这样的数据,我想通过电子邮件对列进行分组,并对不同的列执行不同的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
知道哪个是第一个受骗物品会很有用,因此我们将其处理而忽略其他物品。所以首先,我要标记第一个重复的项目。
这看起来很复杂,但是它的作用是:得到一个list of True vals for all the dupes
并与一个list of True vals for all first dupes.
进行“与”运算
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)
您可以修改合并行功能以对不同的列执行不同的操作。